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 showreports 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
portfolio — compass 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).