Qt Trading Codegen Drift Remediation
Table of Contents
- Context
- Pattern A: Stale HistoryResult wrapper-struct (history dialogs)
- Pattern B: Unconditional offset/limit on non-paginated request (client models)
- Template bug: UUID history dialog branch
- Pattern C: Missing cpp.table_display in domain entity models (runtime test failures)
- Pattern D: tenant_id::from_string crash on bare generation_context (runtime test failures)
- Scope
- Phase 1 — Fix Template UUID Branch
- Phase 2 — Regenerate Stale ores.qt.trading Files
- Phase 3 — Verify Generator and Table Regeneration
- Phase 4 — Audit Other Components
- Key Files and Templates
Context
During the feature/workspace-id-codegen branch build, several files in
ores.qt.trading failed to compile due to stale codegen output — generated
files that were never regenerated after their templates were updated.
Two drift patterns were identified.
Pattern A: Stale HistoryResult wrapper-struct (history dialogs)
All three history dialogs in ores.qt.trading use an old hand-struct pattern:
struct HistoryResult { bool success; std::string message; std::vector<T> versions; };
The current template (cpp_qt_history_dialog.cpp.mustache) generates:
using HistoryResult = std::expected<SomeHistoryResponse, std::string>;
BookHistoryDialog.cpp additionally had the wrong response field name
(->versions instead of ->books), causing a compile error fixed in-place
as a minimal unblock. PortfolioHistoryDialog.cpp and
BookStatusHistoryDialog.cpp compile correctly but diverge from the template.
Pattern B: Unconditional offset/limit on non-paginated request (client models)
ClientBookModel.cpp set request.offset and request.limit on
get_books_request, which no longer has those fields. The template was already
updated to gate these assignments on {{#domain_entity.qt.has_pagination}}.
The book entity model has no has_pagination: true flag, so regeneration drops
those lines. Fixed in-place as a minimal unblock.
Template bug: UUID history dialog branch
In cpp_qt_history_dialog.cpp.mustache, the has_uuid_primary_key branch does:
request.id = id;
where id captures id_, which is boost::uuids::uuid, but request.id is
std::string. This has never caused a build failure because no UUID-primary-key
dialog has been regenerated with the new template. It will fail on next
regeneration of BookHistoryDialog or PortfolioHistoryDialog.
Pattern C: Missing cpp.table_display in domain entity models (runtime test failures)
Three trading domain entity models (lifecycle_event, trade_identifier, trade)
were created without a cpp.table_display array. The template
cpp_domain_type_table.cpp.mustache iterates over this array to emit column
headers and row data. With the array absent, the template generated stub
convert_to_table bodies — empty header row, empty data rows — causing every
table-based unit test to fail with !table.empty().
Fixed in-place by adding cpp.table_display to all three models and updating
the three generated *_table.cpp files to match. As part of the proper codegen
remediation, regeneration must be verified to produce identical output to
confirm the model entries are correct.
Pattern D: tenant_id::from_string crash on bare generation_context (runtime test failures)
The generator template cpp_domain_type_generator.cpp.mustache emits:
r.tenant_id = utility::uuid::tenant_id::from_string(tid_str).value();
where tid_str defaults to "system" when no tenant_id key is present in
the context. "system" is not a valid UUID, so from_string returns an
unexpected value and .value() throws bad access to std::expected without
expected value. Every unit test that calls a generator with a bare
generation_context{} crashes.
Fixed in template and all 23 affected generated *_generator.cpp files:
r.tenant_id = utility::uuid::tenant_id::from_string(tid_str) .value_or(utility::uuid::tenant_id::system());
As part of the proper codegen remediation, all 23 generator files must be regenerated from the corrected template and verified to compile and pass their unit tests.
Scope
Stale output files requiring regeneration:
| File | Pattern | Current state |
|---|---|---|
ores.qt.trading/src/BookHistoryDialog.cpp |
Old wrapper-struct | Compiles (field name fixed in-place) |
ores.qt.trading/src/PortfolioHistoryDialog.cpp |
Old wrapper-struct | Compiles (correct field ->history) |
ores.qt.trading/src/BookStatusHistoryDialog.cpp |
Old wrapper-struct | Compiles (correct field ->history) |
ores.qt.trading/src/ClientBookModel.cpp |
Unconditional offset/limit | Compiles (assignments removed in-place) |
Template bug to fix before regenerating:
| File | Bug |
|---|---|
library/templates/cpp_qt_history_dialog.cpp.mustache |
UUID branch assigns uuid to string |
Phase 1 — Fix Template UUID Branch
File: projects/ores.codegen/library/templates/cpp_qt_history_dialog.cpp.mustache
In the {{#domain_entity.qt.has_uuid_primary_key}} block, change:
request.id = id;
to:
request.id = boost::uuids::to_string(id);
Verify that #include <boost/uuid/uuid_io.hpp> is present in the UUID branch
includes section of the template.
Phase 2 — Regenerate Stale ores.qt.trading Files
Run the generator for the book, portfolio, and book_status domain entity models to regenerate the four stale files:
BookHistoryDialog.hpp/.cppPortfolioHistoryDialog.hpp/.cppBookStatusHistoryDialog.hpp/.cpp(cosmetic only — wrapper-struct drift)ClientBookModel.hpp/.cpp(optional — manual fix already clean)
After regeneration, confirm no new compile errors are introduced by the UUID branch fix.
Phase 3 — Verify Generator and Table Regeneration
After fixing the template bugs (Patterns C and D), regenerate all affected
files and confirm the output matches the in-place fixes made during the
feature/workspace-id-codegen unblock.
Generator files (Pattern D — 23 files)
Regenerate all 23 *_generator.cpp files that had the from_string().value()
call. Confirm they compile and that unit tests calling generators with a bare
generation_context{} pass without exception.
Affected components: ores.reporting.api, ores.refdata.api (11 files),
ores.trading.api (generators + generator directories, 11 files).
Table files (Pattern C — 3 files)
Regenerate:
ores.trading.api/src/domain/lifecycle_event_table.cppores.trading.api/src/domain/trade_identifier_table.cppores.trading.api/src/domain/trade_table.cpp
Confirm output is identical to the in-place fix and that the table unit tests
in ores.trading.api/tests/ pass.
Phase 4 — Audit Other Components
Stale HistoryResult wrapper-struct
The old wrapper-struct pattern likely exists in other Qt components that predate the template migration. Run:
grep -rln "struct HistoryResult" projects/ores.qt.*/src/
File any found as a follow-up story rather than blocking this work.
Missing table_display in other models
Other domain entity models may also be missing cpp.table_display, causing
silent empty-table output. Run:
grep -rL "table_display" projects/ores.codegen/models/**/*_domain_entity.json
Cross-check against entities that have table unit tests to prioritise fixes.
Key Files and Templates
projects/ores.codegen/library/templates/cpp_qt_history_dialog.cpp.mustacheprojects/ores.codegen/library/templates/cpp_qt_client_model.cpp.mustacheprojects/ores.codegen/models/refdata/book_domain_entity.jsonprojects/ores.codegen/models/refdata/portfolio_domain_entity.jsonprojects/ores.qt.trading/src/BookHistoryDialog.cppprojects/ores.qt.trading/src/PortfolioHistoryDialog.cppprojects/ores.qt.trading/src/BookStatusHistoryDialog.cppprojects/ores.qt.trading/src/ClientBookModel.cpp