Task: Reference the anchor from every instrument

Table of Contents

This page documents a task in the Split the trade into an anchor and its components story. It captures the goal, current status, acceptance, and any notes or results.

1. Goal

No instrument table checks its trade against the wide trade; each checks the anchor.

2. Status

Field Value
State DONE
Parent story Split the trade into an anchor and its components
Now Nothing.
Waiting on Nothing.
Next Nothing.
Last touched 2026-10-04

3. Acceptance

  • The 52 trading models that reference ores_trading_trades_tbl reference ores_trading_trade_anchors_tbl, generated from the models.
  • The ORE import still saves its instruments, and the round trip stays lossless in scope.
  • Build, ctest, pgTAP and the local check set pass.

4. Plan

Retarget every instrument's trade reference with a script over the models, regenerate, and fix what the generator assumed about the target.

  • retarget_trade_fk.py points the trade_id foreign key of the 52 models that named ores_trading_trades_tbl at ores_trading_trade_anchors_tbl. The wide trade's own model is left as it is.
  • The reference stays a trigger check rather than a database foreign key: the tenant purger deletes no instrument rows, so an enforced key would stop a tenant that holds instruments from being purged. The acceptance's purge order covers enforced keys only.
  • The generator assumed every trigger-checked target is temporal and filtered on valid_to, which the immutable anchor has no column for. A target whose model is immutable now gets no current-version filter.
  • The derived parent seeding in the generated tests assumed an audited, temporal parent with text lookups; the anchor is neither. A script adds the same parent_seed snippet the booking uses to each model, writing the trade's anchor at the column's group path.
  • The hand-written instrument tests' shared seed writes an anchor instead of a wide trade.

5. Measurements

Every number this task claims about a tree, with the command that produced it and the commit it was measured at. A number without both is not a measurement, because a clean-up record describes a tree and trunk moves under a branch: a consumer count, a gate's component count and a suite's size all change with no code changing, and the reader of a bare number cannot tell which tree it came from. Where the raw output matters, put it in an evidence/ file beside the task and name that file in the Command column.

What Value Command Commit
Models retargeted from the wide trade to the anchor 52 retarget_trade_fk.py (scratchpad) branch head before commit
Merged portfolio round trip, in-scope pairs lost 0, unexplained 0; out of scope lost 314, as before the switch reset_and_roundtrip.sh branch head before commit
Instrument rows the import saved that have an anchor 14 of 14 (12 vanilla swap, 1 cap floor, 1 bond) query on the ACME tenant branch head before commit
ctest suites 90/90 pass compass test run --preset linux-clang-debug-make branch head before commit
Codegen tests 1134 pass, including test_soft_fk_target.py pytest projects/ores.codegen/tests branch head before commit

6. Notes

  • Follow-up: the tenant purger deletes no instrument rows and no wide trades. A purge of a tenant that holds trades leaves them behind.

7. Test Scenarios

Manual QA scenarios (scaffolded via compass add test_scenario) 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
     

8. PRs

PR Title
#2613 [trading] Reference the anchor from every instrument

9. Review

# Comment summary File Decision Notes
1 The generated trigger check filtered the anchor on valid_to, a column it does not have. sql_schema_domain_entity_create.mustache Accept No current-version filter for an immutable target; generator test added.
2 The derived anchor seed in the generated tests did not compile. instrument models Accept A parent_seed snippet, as on the booking.

10. Result

Every instrument and instrument child table now checks its trade against the trade anchor rather than the wide trade. The generator learned that a trigger check against an immutable table reads its row without a current-version filter. The ORE import still saves its instruments, each with its anchor, and the round trip reads as it did before the switch.

Emacs 29.3 (Org mode 9.6.15)