Story: Codegen unified model — Phase 2: single model file per entity
Table of Contents
This page documents a story in Sprint 19. It captures the goal, current status, acceptance criteria, and the tasks that compose it.
ABANDONED 2026-06-01. Superseded by Codegen unified model — org-mode migration. The org-mode migration goes further than the unified-JSON goal proposed here: literate org-mode with custom methods inline, co-located with the component, replacing both JSON model files per entity.
Goal
The current system has two model files per entity:
_table.json— SQL variability (tenant mode, coding scheme, validation function, trigger validations). Created by the SQL refactoring story._domain_entity.json— C++ types, Qt UI, repository settings, NATS protocol. Created incrementally by earlier sprints.
These two files can drift from each other. If a column is added to the SQL model but not the C++ model, generated C++ will be out of sync with the database. There is no cross-validation that enforces agreement. For new entities in non-refdata components, engineers must create two model files and keep them in sync — a maintenance burden that compounds across 75+ entities.
The goal: one _entity.json per entity that drives every code
generation facet: SQL, C++, Qt, CLI, HTTP, shell. Each facet is a
profile; all profiles read the same model. Adding a new facet (CLI, Wt,
HTTP) means adding a section to the JSON Schema and new templates, not a
new model file type.
Unified model design
The _entity.json root key entity subsumes both table and domain_entity:
- SQL variability axes from
table: tenant mode, coding scheme, validation function, trigger logic, indexes. - C++ fields from
domain_entity: cpp_type annotations, includes, generator expressions, repository short names. - Qt fields: derived by Phase 1 or present as genuine variability.
is_temporalflag from Phase 3: replaces the two-family template split.- Profile routing in
profiles.jsonis updated to recogniseentitymodel type.
The unified model is defined by a JSON Schema document committed to
projects/ores.codegen/library/schemas/entity_schema.json.
See Codegen architecture analysis and unified model roadmap for context.
Status
| Field | Value |
|---|---|
| State | ABANDONED |
| Parent sprint | Sprint 19 |
| Now | Nothing. |
| Waiting on | Phase 1: Qt derivation (model is cleaner without transcribed Qt fields). |
| Next | Nothing. |
| Last touched | 2026-06-05 |
Acceptance
- A JSON Schema at
projects/ores.codegen/library/schemas/entity_schema.jsondefines theentityroot key and all variability axes. generator.pyrecognisesentitymodel type;get_model_type()returns"entity"for*_entity.jsonfiles.profiles.jsonroutesentitymodel type to all SQL, C++, and Qt templates.- All refdata
_table.jsonand_domain_entity.jsonpairs are merged into_entity.jsonfiles; both old files are deleted. - Running
--profile sqlon a refdata_entity.jsonproduces zero diff against the current production SQL. - Running
--profile all-cppon a refdata_entity.jsonproduces zero diff against the current production C++ files. - All remaining components (trading, iam, dq, analytics, reporting, scheduler, workflow, workspace) have their models migrated.
_table.jsonand_domain_entity.jsonmodel types are removed fromgenerator.pyandprofiles.json.- Codegen CI zero-diff invariant is green. CI passes. Site builds cleanly.
Tasks
| Task | State | Start | End | Description |
|---|---|---|---|---|
| Task: Design the unified entity JSON Schema | BACKLOG | Define entity root key; enumerate all SQL variability axes from _table.json and all C++ fields from _domain_entity.json; write entity_schema.json; validate it against all existing models. | ||
| Task: Implement entity model type in generator.py and profiles.json | BACKLOG | Add entity model type detection; update get_model_type(); update resolve_output_path() for entity type; update profiles.json to route entity to all facets. | ||
| Task: Migrate refdata models (pilot) | BACKLOG | Merge all refdata _table.json and _domain_entity.json pairs into _entity.json; verify zero SQL diff and zero C++ diff; delete old files. | ||
| Task: Migrate all remaining components | BACKLOG | Apply the same migration to trading, iam, dq, analytics, reporting, scheduler, workflow, workspace; verify zero diff per component. | ||
| Task: Retire _table.json and _domain_entity.json model types | BACKLOG | Remove old model type branches from generator.py; remove old model type routing from profiles.json; confirm no models directory contains old-format files. |
Decisions
- JSON Schema as the contract.
entity_schema.jsonis the machine-readable contract validated before generation. This catches missing required fields at model-parse time, not at diff-check time. - Rename files, not roots. The unified file is
*_entity.json(replacing both*_table.jsonand*_domain_entity.json). The root key isentity. This avoids confusion with the old*_entity.jsonnaming that some components used before the SQL refactoring. - Dispatch on root key, not filename suffix. Several components (trading, dq,
iam) already have
*_entity.jsonfiles whose root key isschema— the old model format from before the SQL refactoring.get_model_type()ingenerator.pymust inspect the JSON root key (entityvs.schemavs.tablevs.domain_entity), not the filename suffix, to avoid silently misrouting legacy schema files as unified entity models. - Refdata pilot first. Refdata has the cleanest models after the SQL refactoring and C++ audit. Migrating refdata first produces the reference implementation.
Out of scope
- Adding CLI, HTTP, shell, or Wt sections to the unified model — that is a follow-on story per facet once the unified model exists.
- Changing C++ API design or adding new template features.
- CMakeLists.txt generation — CMake files have non-trivial manual content and are managed separately.