Task: Retire the curve parameter paths the schema does not declare

Table of Contents

This page documents a task in the Standardise the curve configuration's parameters on the one contract story. It captures the goal, current status, acceptance, and any notes or results.

1. Goal

Every curve parameter's path is a path the ORE schema declares, or one the ORE code reads where the schema omits it, stated with the reason.

2. Status

Field Value
State DONE
Parent story Standardise the curve configuration's parameters on the one contract
Now Nothing.
Waiting on Nothing.
Next Nothing.
Last touched 2026-10-29

3. Acceptance

  • The extractor attributes a block to the class of the call that follows its read, bounded by the next block, rather than the last call that names its variable.
  • The four ParametricSmileConfiguration paths under Parameters and Calibration are gone from the published artefact, and the ResidualCorrection path remains.
  • The one path the schema omits but the ORE code reads is recorded where the schema check reads it, with the ORE source line, so it fails the check no more.
  • A check walks every curve parameter path through the schema from CurveConfiguration and fails on a path a parent does not declare, wired into the local checks.
  • The check is run against the committed artefact, and against the artefact of the commit before the fix, where it fails.

4. Plan

1. Attribute a block to the call that follows its read, bounded by the next Read
   of the same variable, and leave a variable a sibling's call names without a
   call inside the block unattributed.
2. Add curve_schema_exemptions.json: one rule for the settings ORE reads and
   writes on the segment base while the per-kind types declare a subset, and one
   for the yield volatility's Interpolation.
3. Add check_curve_parameter_paths.py, which walks every path of the committed
   artefact through curveconfig.xsd and fails on a path a parent does not
   declare, and fails on an exemption no path needs.
4. Wire it into the local checks and prove it against the artefact of the commit
   before the fix.

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
Curve paths checked 309 python3 projects/ores.sql/utility/check_curve_parameter_paths.py this branch
Problems after the fix 0 as above, exit 0 this branch
Problems before the fix 4 as above with --artefact on the pre-fix artefact, exit 1 9b358a3bf4
Artefact parameters 2343, then 2339 python3 projects/ores.sql/utility/generate_ore_parameters_dataset.py this branch
Leaves the extractor reads 486, then 483 python3 projects/ores.sql/utility/extract_curve_terms.py this branch
Exemption rules 2 projects/ores.sql/utility/curve_schema_exemptions.json this branch

6. Notes

  • What makes a path wrong. The contract keys a leaf by an XPath and every reader resolves it against the document. A path that no document holds describes a leaf that cannot be drawn and cannot be guarded: the store and the page both do nothing with it, without an error.
  • Five paths fail today, found by walking the published artefact through `curveconfig.xsd` from `CurveConfiguration`, where a path may only continue through a complex type:
    • `/CurveConfiguration/FXVolatilities/FXVolatility/ParametricSmileConfiguration/Parameters/Dimension`
    • `/CurveConfiguration/FXVolatilities/FXVolatility/ParametricSmileConfiguration/Calibration/Dimension`
    • `/CurveConfiguration/SwaptionVolatilities/SwaptionVolatility/ParametricSmileConfiguration/Parameters/Dimension`
    • `/CurveConfiguration/SwaptionVolatilities/SwaptionVolatility/ParametricSmileConfiguration/Calibration/Dimension`
    • `/CurveConfiguration/YieldVolatilities/YieldVolatility/Interpolation`
  • The four smile paths are one cause. `ParametricSmileConfiguration::fromXML` reads its three blocks into the same variable name, `n`, and the extractor keys the block's parser by that variable, so the last call wins and every block is walked as `ResidualCorrection`, whose single read is `Dimension`. The real `Parameters` block holds repeated `Parameter` nodes and the real `Calibration` block holds three leaves, so the sibling attribution wants the call that follows the block's own read, bounded by the next block. A repeated child is a collection the extractor does not model yet, which is why the `Parameters` block may end up recorded as unresolved rather than wrong.
  • `Interpolation` is the schema's gap, not the code's. `genericyieldvolcurveconfig.cpp:236` reads `Interpolation` for a yield volatility, and `yieldVolatility` in `curveconfig.xsd` declares no such element. The path is real, so the check needs the statement that the ORE code reads it, with that source line, rather than an exemption a reader cannot verify.

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
#4126 [agile] Close the curve configuration story
#4124 [refdata] Attribute a block to the call that follows it

9. Review

Comment summary File Decision Notes
       

10. Result

A block is attributed to the call that follows its read, so the four ParametricSmileConfiguration paths under Parameters and Calibration are gone, ResidualCorrection/Dimension remains, and the Calibration block's three real leaves appear where a copied Dimension stood. The Parameters block is recorded as unresolved, which is the truth: it holds repeated Parameter nodes the extractor does not model.

The artefact drops from 2343 parameters to 2339.

check_curve_parameter_paths.py walks 309 paths through the schema and passes. Against the artefact of 9b358a3bf4 it fails on the four smile paths, which is the proof it can fail for the reason it exists.

Two paths the schema does not declare stay, each with the ORE source line that reads it: the four settings every segment shares, which ORE's base class reads and writes while the per-kind types declare a subset, and a yield volatility's Interpolation, which genericyieldvolcurveconfig.cpp:236 reads though yieldVolatility declares no such element.

Emacs 29.3 (Org mode 9.6.15)