Task: Migrate tenor entities to ores.refdata, add tenant provisioner copy fix and Tenor Management UI

Table of Contents

This page documents a task in the IR Rates synthetic data generation story. It captures the goal, current status, acceptance, and any notes or results.

Goal

Migrate tenor/tenor_anchor/tenor_convention/tenor_convention_resolution out of ores.marketdata into ores.refdata, regenerating the full codegen stack (domain, eventing, messaging, generator, repository, Qt) in the new location. Fix the tenant provisioner to copy the four tenor reference tables into new tenants (verified: provisioning a test tenant copies 5/37/3/39 rows correctly). Then build a hand-authored Tenor Management Qt screen showing, per convention, every tenor's resolved anchor/offset (from tenor_convention_resolution overrides or tenor_convention/tenor defaults), so the combined data model can actually be inspected and validated end-to-end.

Status

Field Value
State DONE
Parent story IR Rates synthetic data generation
Now Nothing.
Waiting on Nothing.
Next Nothing.
Last touched 2026-07-13

Acceptance

  • Provisioning a new tenant copies all four tenor tables from the system tenant (verified via ores_iam_provision_tenant_fn) — DONE, extended to all six tenor-related tables after the code-entity promotion (see Result)
  • A new Qt screen lets a user pick a convention and see every tenor's resolved anchor and offset in one table, using the tenor_resolution resolver — DEFERRED (see Result)
  • Screen is reachable from the main window/menu like other list windows — DONE for the per-entity CRUD screens (codegen'd); N/A for the deferred joined view

Plan

(Implementation strategy. Written when work starts; key decisions are distilled into the parent story's * Decisions at close, but the plan itself stays — it is the historical record of what we did.)

Notes

Test Scenarios

Manual QA scenarios (scaffolded via compass add test_scenario, run through the QA Validation Runner panel) that verify this task. Link new ones here as they're created; the scenario doc itself links back via its "Verifies task" field.

Scenario State Notes
Tenor reference-data screens reachable from Reference Data menu PASSED Rerun after change-reason wiring, badges, combo boxes, related-entity toolbar shortcuts, and Anchor icon fix

PRs

PR Title
#1554 [refdata,qt,sql] Migrate tenor entities to ores.refdata, add Tenor Management UI

Review

PR #1554 review round (Claude automated, issue-level comment, no line comments):

# Comment summary File Decision Notes
1 No cross-field validation between tenor.kind and tenor.unit/multiplier (e.g. SPECIAL + MONTH is not blocked) TenorDetailDialog Declined UX/data-quality nicety, not a bug in what shipped; FK validation on kind/unit individually is correct and complete. Candidate follow-up if it matters in practice
2 tenor_convention_resolution has no dedicated event registrar ores.refdata/core/src/messaging/registrar.cpp Declined Intentional and pre-existing (unrelated to this PR) — it's a hand-authored, read-only junction with no save/delete mutation path, so there's nothing to publish an event for
3 No new automated tests for tenor_kind/tenor_unit/tenor_resolution_algorithm (new entities) Declined Matches existing convention for simple code-lookup entities (book_status also has none); coverage via manual test_scenario

Result

Migrated tenor/tenor_anchor/tenor_convention/tenor_convention_resolution from ores.marketdata to ores.refdata with a full codegen regeneration (domain, generator, repository, service, protocol, eventing, handler, Qt) across all layers. Fixed the tenant provisioner, which wasn't copying any of the tenor tables into new tenants; verified against a live Barclays Plc provisioning that all counts now match the system tenant exactly.

Along the way, promoted tenor.kind, tenor.unit, and tenor_convention.resolution_algorithm (previously unvalidated free text) to proper FK-validated ores.refdata code entities (tenor_kind, tenor_unit, tenor_resolution_algorithm), following the book_status pattern — full codegen stack, dynamic combo boxes in the detail dialogs, and badges for Kind/Unit. tenor_convention .measured_from became a validated combo against tenor_anchor, which gained its own display_order column and validation function (both previously missing). Added NONE sentinel codes to tenor_unit and tenor_anchor so these FK columns could be non-nullable. Wired the generated event registrars and NATS sub-registrars for all affected entities into their service-side aggregators — the original migration had left them unregistered, so saves never published change events or enabled live eventing. Added toolbar shortcuts between related entities (Tenor ↔ Conventions/Anchors, Tenor Convention ↔ Anchors/Resolution Algorithms) via the codegen "Related entity shortcuts" mechanism. Added an Icon::Anchor icon (Fluent Pin / Solar pin.svg — neither icon set has a literal nautical-anchor glyph) replacing the generic Clock icon Tenor Anchor had been using.

Reference Data > Tenors menu: Tenors and Tenor Conventions at the top; Tenor Anchors/Kinds/Units/Resolution Algorithms directly below a separator (no nested submenu).

Verified: test_scenario PASSED (menu reachability, list windows, detail dialog, history dialog); a live Barclays Plc reprovision confirmed the tenant-copy fix for the six tenor-related tables (2/5/6/2/37/3 rows each, matching the system tenant exactly); local build clean (linux-clang-debug-make); ctest 71/72 passed — the one failure (ores.analytics.quant.tests, "concurrent updates and batched reads never crash or hang") is a pre-existing Catch2 output-redirect race in an unrelated analytics/quant concurrency test, confirmed unrelated by isolated rerun.

Deferred: the hand-crafted joined Tenor Management screen (tenor x tenor_convention x tenor_convention_resolution resolved anchor/offset in one view) from this task's original acceptance criteria was not built — the codegen'd per-entity CRUD screens (now with combo boxes and badges) satisfy inspecting the data model end-to-end for this round; the joined resolved view remains a candidate follow-up capture if still wanted.

Emacs 29.3 (Org mode 9.6.15)