Story: Regroup C++ components under product-group parent directories
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.
Goal
Each product group (refdata, trading, iam, dq, analytics, reporting,
scheduler, workflow, controller, database, workspace, compute) owns a
single parent directory under projects/, with its sub-components
(api, core, service, the qt UI) as children of that parent, plus
a modeling/ directory that holds the group's codegen entity models.
Today the layout is flat:
,projects/ ,├── ores.refdata.api/ ,├── ores.refdata.core/ ,├── ores.refdata.service/ ,├── ores.qt.refdata/ ,└── ores.refdata/modeling/ ← orphaned; added by the org-mode pilot
The target layout groups by product (decisions D1–D3 resolved the
open choices — short child names, Qt under ores.qt/, no group-root
CMakeLists):
,projects/ ,├── ores.refdata/ ← domain group ,│ ├── api/ ,│ ├── core/ ,│ ├── service/ ,│ └── modeling/ ← group models (separate story) ,└── ores.qt/ ← Application-layer group , ├── application/ ← the MDI host app , ├── api/ , ├── refdata/ ← refdata Qt plugin , ├── party/ , └── … ← every other Qt plugin
This makes the codegen "models belong to the group" property literally
true on disk and makes IDE navigation match the conceptual layout. The
Qt plugins group under ores.qt/ because they are the Application
layer projecting the Domain layer — a separate architectural band from
the domain group they present (see D2).
Why now
Driven by the Codegen unified model — org-mode migration story. The
pilot moved party to projects/ores.refdata/modeling/, but
projects/ores.refdata/ is an orphan: it has no CMakeLists, no
sub-components, no role. Continuing the migration without first
regrouping pushes the same orphan into every group. Better to land the
regroup now and have every per-group migration task land into a real
populated group folder.
Relationship to other stories
- Blocks Codegen unified model — org-mode migration for per-group
tasks beyond refdata. The refdata pilot can proceed in parallel
because
projects/ores.refdata/modeling/already exists. - Tracks against Refactor ores.codegen C++ generation — the codegen
template output paths and the manifest
models_dir/modeling_dirreferences that this story may touch.
Status
| Field | Value |
|---|---|
| State | DONE |
| Parent sprint | Sprint 19 |
| Now | Nothing. |
| Waiting on | Nothing. |
| Next | Nothing. |
| Last touched | 2026-06-02 |
Regroup complete: all groups moved to ores.<group>/<short>/, Qt under
ores.qt/, host as ores.qt/application/, move-invariant include paths;
build configures, compiles, and services start and run clean. Shipped in
PR #997 along with two pre-existing-breakage fixes surfaced by the clean
build (the swap-parse TU and the init-environment service glob). The
service-registry consolidation discovered here was promoted to its own
story, Consolidate standalone scripts into compass (not a blocker for
this story).
Acceptance
- Every domain product group has a single parent directory at
projects/ores.<group>/containing itsapi/core/servicesub-components under short names. - All Qt UI components live under
projects/ores.qt/(the host asapplication/, each plugin as a short-named sibling); no Qt plugin remains beside its domain group (D2/D3). - The flat
projects/ores.<group>.<role>/andprojects/ores.qt.<group>/directories no longer exist. cmake --build --preset linux-clang-debug-makepasses; the build output is functionally identical to pre-regroup.ctestpasses.- Codegen output paths: surveyed — no per-component path references in the profile manifest or templates, so nothing to change (Q4).
- CI workflows and presets: surveyed — none carried per-component paths.
One path-bearing script was missed in the initial survey:
build/scripts/init-environment.shglobsprojects/ores.*.serviceto discover NATS services, which the regroup broke (CI "Setup Database" failure). Fixed by reading the existing service registry instead; full consolidation tracked by Consolidate standalone scripts into compass. - Include paths made move-invariant (D4) rather than re-pointed to the new absolute layout, so future moves do not re-break them.
Note: the group modeling/ directory is owned by the
org-mode migration story, not this one. Orphan modeling/ dirs left
by the pilot are left in place for that story to populate.
Tasks
| Task | State | Start | End | Description |
|---|---|---|---|---|
| Investigate target layout for component regrouping | DONE | 2026-06-01 | 2026-06-02 | Decided naming (short), qt under ores.qt/, host as application/, relative includes. Subsumed implementation — regroup done in one pass. |
No per-group migration tasks were scaffolded: the regroup is a mechanical, atomic change and was carried out in a single pass under the investigation task. Splitting per group would have created merge churn for no benefit.
Notes
Group-level documentation lives at the group, not at a child
Any documentation that describes the product group as a whole
(architecture notes, design overviews, plantuml diagrams covering more
than one sub-component, knowledge docs about the domain) lands under
projects/ores.<group>/ — typically under projects/ores.<group>/modeling/
alongside the entity models, or a sibling projects/ores.<group>/doc/
if the volume justifies it.
Avoid putting cross-cutting docs under any specific child like
projects/ores.<group>.api/: they are no more about the API than they
are about the core, and parking them in one child makes the others
look like the wrong place to find them. The same logic that drove the
regroup itself — "the property belongs to the group, not the children"
— applies to documentation too.
Per-component documentation (something genuinely API-specific, or core-specific) still lives in the child component.
Decisions
D1. Child directory naming: short names
Child component directories use short names — api, core,
service, client, server, wrapper, database — under the group
parent. Example: projects/ores.refdata/api/, not
projects/ores.refdata/ores.refdata.api/. The group folder already
disambiguates; the doubled prefix was judged excessive. CMake target
names keep the fully-qualified form (ores.refdata.api.lib) for the
compiler and linker; only the on-disk folder is shortened. C++ include
prefixes are unaffected — they are set by the include/ores.refdata.api/
tree inside each component, which moved intact.
D2. The Qt UI components live under ores.qt/, not the domain group
All Qt UI components are grouped under projects/ores.qt/ rather than
beside the domain group they present. Rationale: the Qt plugins are the
Application layer projecting the Domain layer — they are not a facet
of the domain, they are a separate layer over it. The C++ namespace
(ores::qt::refdata), the inter-plugin CMake dependencies (e.g. the
scheduler plugin includes the compute plugin), and the precedent of
ores.wt.service (a standalone UI, not buried in a domain group) all
agree. Plugins keep their namespace-suffix short names:
ores.qt/refdata/, ores.qt/admin/, ores.qt/mktdata/, ores.qt/party/,
etc.
D3. The Qt host app is ores.qt/application/
ores.qt/ is a pure group folder — no component lives at its root.
The MDI host application (formerly the ores.qt component at
projects/ores.qt/) moves to projects/ores.qt/application/ as a
sibling of all the plugins. This avoids mixing levels (a component at
the group root alongside child components) and keeps every child of
ores.qt/ a uniform component folder.
D4. Include paths: relative and move-invariant
Self-include references in component src/CMakeLists.txt changed from
the fragile absolute form
${CMAKE_SOURCE_DIR}/projects/<fq-name>/include to the move-invariant
${CMAKE_CURRENT_SOURCE_DIR}/../include. The set(ORES_QT_*_DIR ...)
self directory variables likewise became ${CMAKE_CURRENT_SOURCE_DIR}/...
Cross-component include references were repointed to the new group
locations. This removes the class of breakage that the move itself
exposed: a future relocation of any component no longer requires editing
its own include paths.
D5. Group root CMakeLists (Q3)
Not introduced. projects/CMakeLists.txt continues to add_subdirectory
each leaf component directly (now at ores.<group>/<role>). A group-root
CMakeLists that factors common settings was judged a separate concern;
the build works without it and the regroup stays minimal.
Survey outcomes (Q4, Q5)
- Codegen output paths: no
projects/ores.<group>.<role>references found in theores.codegenmanifests or templates — nothing to change. - CI / presets:
.github/workflows/andCMakePresets.jsoncarry no per-component paths — nothing to change. projects/CMakeLists.txtwas the only file holding the componentadd_subdirectorylist; all 90+ leaf components updated there.- Component
src/CMakeLists.txtinclude paths: ~90 references updated (self → relative, cross → new location). - C++
#includedirectives: unaffected (include/ trees moved intact).
Out of scope
- Renaming the product groups themselves.
refdata,trading, etc. stay as they are; this is purely a directory regrouping. - Changing C++ include paths. The headers stay installed under
ores.refdata.api/foo.hpp; this is a directory move, not a namespace move. - Splitting or merging components within a group.
api,core, andserviceremain three components per group.