Task: Codegen full stack for portfolio and address codegen drift

Table of Contents

This page documents a task in the Commission: portfolio story. It captures the goal, current status, acceptance, and any notes or results.

Goal

Bring portfolio onto a clean, fully-regenerated codegen baseline across every layer the meta-model supports (api/core/sql at minimum, plus shell/cli/qt/wt/http where already scaffolded), updating ores.refdata.portfolio.org as needed, then reconcile any drift the same way book was remediated in Book codegen drift remediation: identify stale layers via compass codegen entity show, regenerate, and confirm no SQL validations (soft FKs, value checks, insert triggers) were silently dropped in the process.

Status

Field Value
State DONE
Parent story Commission: portfolio
Now Nothing.
Waiting on Nothing.
Next Nothing.
Last touched 2026-07-16

Acceptance

  • [ ] compass codegen entity show reports all-✅ for portfolio.
  • [ ] Any SQL validations present before regeneration are confirmed still present afterwards, via paste blocks or variability knobs — not hand-patched.
  • [ ] portfolio builds cleanly on the configured preset; existing tests pass with no regressions.

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
     

PRs

PR Title
#1616 [refdata,qt,codegen] Regenerate portfolio against current codegen templates

Review

# Comment summary File Decision Notes
1 High: unconditional import fcntl breaks Windows projects/ores.compass/src/compass.py Fixed Guarded import, build-lock functions skip locking with a one-time warning when fcntl is unavailable
2 High: portfolio detail/list UI silently lost status/is_virtual/description/badge styling during regen projects/ores.refdata/modeling/ores.refdata.portfolio.org, generated Qt files, dq_badge_mappings_artefact_populate.sql Fixed Added the three fields to Detail fields (status default+static_combo, is_virtual check_box w/ int->bool, description text_edit), Status/IsVirtual badge columns matching pre-seeded portfolio_status/is_virtual badge-mapping rows; parent_portfolio_id/owner_unit_id left unexposed, matching book's owner_unit_id precedent
3 Medium: half-finished event-registrar migration (dead code) projects/ores.refdata/service/src/messaging/event_registrar.cpp, …/app/application.cpp Fixed Wired register_portfolio_event_mapping into event_registrar.cpp, removed the now-redundant hand-wired registration/subscription and include from application.cpp
4 Low: 2-slot build lock still allows a race projects/ores.compass/src/compass.py Declined Reduces the race window from unbounded to 2 concurrent builds by design; a stricter single-slot lock was the initial ask before a follow-up request specifically asked for 2
5 Low: lock-status file write is non-atomic projects/ores.compass/src/compass.py Declined Display-only race (a –status read could transiently see an empty file); not worth the added complexity of an atomic rename for a status command
6 Low: portfolio_repository batch remove() omits workspace_id filter projects/ores.refdata/core/src/repository/portfolio_repository.cpp Declined Faithful mirror of the same pre-existing gap in book_repository.cpp (codegen template output), not a portfolio-specific regression – fixing the template is out of scope here

Result

Diffed ores.refdata.portfolio.org against book's model and fixed every gap found: corrected domain_include=/=protocol_include paths (missing .api), added the missing party_id=/=owner_unit_id Foreign keys sections, added Insert trigger validations for purpose_type (existing ores_refdata_validate_purpose_type_fn) and aggregation_ccy (ores_refdata_validate_currency_fn) with a default_value for purpose_type so the Add dialog's default state passes the new trigger, and added the has_change_reason_cache=/ =has_export_macro=/=has_explorer_api=/=parent_entity_singular Qt knobs (the latter two required once regeneration surfaced that PortfolioExplorerMdiWindow calls openAdd=/=openAddWithParent=/ =openEdit=/=openHistory on the controller). Converted purpose_type to a dynamic combo (new fetch_purpose_types in LookupFetcher) and aggregation_ccy to a currency flagged combo with a list-view flag icon, matching book's book_status=/=functional_currency UX instead of leaving them as free-text fields once FK validation was added.

Full stack regenerated via compass codegen entity generate portfoliocompass codegen entity show portfolio is all-✅ across api/core/service/qt/sql (39 files).

Moved PortfolioController construction and menu/toolbar wiring from TradingPlugin to RefdataPlugin (no cross-component leakage), mirroring the earlier book move: RefdataPlugin now owns the &Portfolios action, TradingPlugin consumes a non-owning portfolio_controller() pointer for the Portfolio/Org Explorer composite views. Deleted the superseded hand-written trading Controller/DetailDialog/MdiWindow/ClientPortfolioModel/HistoryDialog files.

Found and fixed, unrelated to portfolio itself: missing ores.diff.lib=/=ores.eventing.core.lib link edges in ores.dq.core=/=ores.dq.service (build breaks pre-dating this branch), a stale e.ids field reference in refdata service's application.cpp (portfolio_changed_event's field is portfolio_ids), and two pre-existing SQL RLS gaps (curve_role, yield_curve_process_type had tenant_id but no tenant-isolation policy) surfaced by validate_schemas.sh.

Also added a host-wide build lock to compass build (two flock-based slots, -j2=/-j3=, per-slot live log streaming to /tmp/ores-build.log.<slot>, --status) after a concurrent build from another environment corrupted a shared library mid-session (libores.workflow.core.so truncated to 0 bytes) — multiple worktrees on this host build concurrently and were doing so uncoordinated. Updated every LLM-facing build recipe/skill to route through compass build instead of raw cmake --build.

Verification: full build green (linux-clang-debug-make); ores.refdata.*.tests pass except 2 known pre-existing failures (party_identifier_generator=/=counterparty_identifier_generator, tracked separately, unrelated to this change); validate_schemas.sh 0 warnings (was 2, both fixed).

Emacs 29.3 (Org mode 9.6.15)