Task: Add a store transform to the mapper and state it on the convention columns

Table of Contents

This page documents a task in the Let the model state how the store keeps a column story. It captures the goal, current status, acceptance, and any notes or results.

1. Goal

Make the convention normalisation a property of the model, so a regeneration keeps it.

2. Status

Field Value
State DONE
Parent story Let the model state how the store keeps a column
Now Nothing.
Waiting on Nothing.
Next Nothing.
Last touched 2026-10-31

3. Acceptance

  • A column states a store transform and the header that declares it
  • The generated mapper calls the transform on the way into the row, and not on the way out of it
  • A column whose domain member is optional keeps absence absent through the transform
  • The eleven refdata convention columns state the transform in their models, and a regeneration keeps the call and its include

4. Plan

The mapper template already branches on the shape of a column, and the store transform has to follow the same three shapes: a plain column passes the value, a nullable string passes the value or the empty string, and a column whose domain member is std::optional<T> maps inside the optional. The first two branches took the transform, and the third is what the convention columns actually are: their models state :cpp_type: std::optional<std::string> with :nullable: true, so the mapper reaches them through is_already_optional.

The header is a gate like the enum and date includes: the model names it, the gate lists it once, and the template emits it in the same include block.

The eleven columns then state the transform, and a regeneration writes the call. The hand edit is gone, so nothing has to be re-applied after a codegen run.

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
refdata suite 488 cases, 5723 assertions, 0 failures =compass test run – -R 'ores.refdata.core.tests ores.ore.core.tests'= branch head
ore core suite 425 cases, 478415 assertions, 0 failures same branch head
codegen tests 1695 passed projects/ores.codegen/venv/bin/python -m pytest projects/ores.codegen/tests branch head
refdata drift no drift check_component_drift.py --component refdata branch head
regeneration of the refdata repository no change to the tree compass codegen regenerate --component refdata --address ores.cpp.repository then git status branch head

6. Notes

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
#4196 [agile] Close the store transform story
#4193 [codegen,refdata] Let the model state how the store keeps a column

9. Review

Comment summary File Decision Notes
       

10. Review

# Comment summary File Decision Notes
1 The three column shapes each need the call, and the convention columns are the already-optional shape cpp_domain_type_mapper.cpp.mustache Fixed before the PR The first two branches took the transform and the third did not, which the regenerated output showed
2 A codegen change renders the whole estate, so the gate also reads what main carries drifted two generated files Accepted, separate task Closed by the sibling task in this story

11. Result

The transform is a property of the model. A generated mapper applies it on the way into the row, keeps absence absent where the domain member is optional, and includes the header once. The eleven convention columns state it, and a regeneration against the tree changes nothing.

The document round trip and the ORE example suite both pass, so the store keeps the seven codes while the documents keep the spellings they state.

Merged as PR #4193, together with the sibling task that repaired the two generated files main carried drifted.

Emacs 29.3 (Org mode 9.6.15)