Qt Trading Codegen Drift Remediation

Table of Contents

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 / .cpp
  • PortfolioHistoryDialog.hpp / .cpp
  • BookStatusHistoryDialog.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.cpp
  • ores.trading.api/src/domain/trade_identifier_table.cpp
  • ores.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

Date: 2026-05-19

Emacs 29.1 (Org mode 9.6.6)