Task: Hold the FRA notional and strike as the document's digits

Table of Contents

This page documents a task in the Rework the rates instruments to the instrument table rule story. It captures the goal, current status, acceptance, and any notes or results.

1. Goal

A FRA's notional and strike are stored as the exact decimal the document wrote, and the exporter writes the same digits back. 0.0065 is stored as 0.0065, not as 0.006500000134110451.

2. Status

Field Value
State DONE
Parent story Rework the rates instruments to the instrument table rule
Now Nothing.
Waiting on Nothing.
Next Nothing.
Last touched 2026-10-11

3. Acceptance

  • The ORE binding keeps the digits of the FRA notional and strike, through the reapply script, not by hand.
  • The forward mapper stores the document's digits for both, and the reverse mapper hands them back.
  • A mapper test holds the digits of a FRA strike and notional through the round trip.
  • The golden files that change are regenerated and every changed line is a numeric leaf.
  • The corpus proof and the ORE suite pass.

4. Plan

  1. The binding. Make the FRA's Strike and Notional a lexical leaf, moneyFloat, instead of a bare float. The change is made by scripts/reapply_ore_lexical_form.py on domain.hpp and domain.cpp, so a regenerated binding keeps it. The script refuses to patch when an anchor is missing or not unique.
  2. The mapper. The forward mapper already reads a lexical leaf through exact_decimal, so it now stores the document's digits. The reverse mapper hands the stored digits back with set_exact.
  3. Tests. Correct the FRA forward test, which pinned the float artifact, and add a test that the digits survive the reverse mapping.
  4. Goldens. Regenerate the one golden that changes and check that the change is numeric text only.

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
FRA strike of IR_FRA.xml, stored 0.005 (was 0.005 widened from a float) ores.ore.core.tests mapper_roundtrip_fra_forward the PR head
ORE core suite 649 cases, 482,966 assertions, all pass ores.ore.core.tests the PR head
Golden files changed 1 (IR_FRA.xml, one numeric line) git diff -U0 -- assets the PR head
Reapply script self-tests both pass on three files scripts/reapply_ore_lexical_form.py --self-test and --self-test-missing-anchor the PR head

6. Notes

  • The binding has 152 bare float members. Only the FRA's two are changed here, because the FRA is the case that stored a wrong value. The others are not audited by this task.
  • The new leaf is a plain xsd::base<float> with its own setter, element info and serializer, so the existing leaf types are not touched.

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
#3129 [ore] Hold the FRA notional and strike as the document's digits

9. Review

# Comment summary File Decision Notes
1 The FRA forward test pinned the float artifact as the expected strike xml_ir_mapper_roundtrip_tests.cpp accept It now expects the document's 0.005.
2 The serializer anchor for the FRA body occurs in two structs reapply_ore_lexical_form.py accept The anchor starts at the FRA's Index line, and the script refuses a non-unique anchor.
3 The idempotence guard returns early when moneyFloat appears anywhere reapply_ore_lexical_form.py accept Every edit must be present or none; a partial state is refused.
4 A comment names a where element the edit tuples do not have reapply_ore_lexical_form.py accept Comment corrected.
5 Pin the serializer's fallback for a FRA built in code reapply_ore_lexical_form.py decline The fallback is the shared get_string(float, lexical), which the a leaf set in code test already holds.
6 Check the serialized XML after the reverse mapping xml_ir_mapper_roundtrip_tests.cpp accept The FRA digits test now writes the trade and checks <Strike>0.005</Strike>.
7 List the other bare float members in a follow-up none decline Left to the operator; the Result states the scope.

10. Result

A FRA's strike and notional are stored as the digits the document wrote and exported as the same digits. IR_FRA.xml states a strike of 0.005; the mapper stored the float nearest to it and the exporter wrote 0.00499999989. The binding now holds both members as a lexical leaf, through the reapply script, the mapper reads and writes the digits, and the one golden that changed holds the document's text.

Acceptance met: the binding keeps the digits through the script, both mapper directions carry them, a test holds them through the reverse mapping, the golden change is one numeric line, and the ORE suite passes.

Other bare float members of the binding are not covered, and no task is open for them.

Emacs 29.3 (Org mode 9.6.15)