Task: Declare the conventions bundle

Table of Contents

This page documents a task in the Refactor conventions onto families and bundles story. It captures the goal, current status, acceptance, and any notes or results.

1. Goal

A caller writes conventions one bundle at a time instead of one whole document. The bundle opens, stages one row per family, and commits once, so every family in the bundle lands together or none of it does. The reply names each family and what became of it.

2. Status

Field Value
State DONE
Parent story Refactor conventions onto families and bundles
Now Nothing.
Waiting on Nothing.
Next Nothing.
Last touched 2026-10-18

3. Acceptance

  • Three operations are the only way a caller writes conventions, and each is its own message. Begin opens an import, stage adds one family, commit applies them.
  • The commit applies every staged family inside one unit_of_work, so one failing family rolls the whole import back.
  • The commit reply names an outcome for each family, and separates the world rows that already existed.
  • The reply names the FX conventions the boundary skipped.
  • A retried begin names the import it already opened. A commit on an import that is not staging is refused.
  • A fresh database build creates the import and staging tables, so an empty environment can import on its first day.

4. Plan

The plan was one operation at a time, begin then stage then commit, with the staging tables first so the commit had somewhere to read from.

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
       

6. Notes

  • The unit is a bundle, not a document. The staging rows carry the family payloads, so the commit message carries only the import id and no family data crosses the wire at commit time.
  • The staging tables are ores_refdata_bundle_imports_tbl and ores_refdata_bundle_import_items_tbl. The models were first written as conventions import tables and renamed when the unit became general.
  • A fresh database build missed the two tables because the refdata create script listed no \ir line for them. The tables existed only because a development database had been migrated in place.
  • The staged dispatch covers every family the registry names, which is what the staged dispatch has a branch for every registry family checks. The transaction behaviour has no test of its own, so the rollback claim rests on the unit_of_work destructor and not on a test.
  • commit_bundle_import_response declares fx_skipped and nothing assigns it. The request is served, but the FX conventions the boundary skipped are reported by the ORE caller from the package it mapped, not by the commit. Filling the field is open work.
  • An import leaves one applied row in the bundle import tables. A run import therefore writes rows the record did not have before.

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
#3465 [refdata] Model the conventions import staging tables
#3467 [refdata] Begin, stage and commit a conventions import
#3468 [agile] Stamp the bundle task started
#3482 [web] Commit the generated conventions TypeScript
#3485 [refdata,ore] Rename the import staging to bundle import

9. Review

Comment summary File Decision Notes
       

10. Result

Merged. A caller now opens an import with begin_bundle_import, adds one family per stage_bundle_family, and applies the set with commit_bundle_import. The commit takes the import row's lock, reads the staged rows in ascending id order, and sorts them into registry order before it applies each through the generated apply_staged_family inside one unit_of_work. The apply sees registry order, and the caller's sequence breaks the ties inside one family, so the order the stages landed in decides nothing. A family that fails to decode throws, the unit of work rolls back, and the import stays staging. The reply carries an outcome per family and the world rows that were already there.

The reply declares fx_skipped and never fills it. The ORE callers work out the skipped FX conventions themselves. Filling the field is open work, so the acceptance criterion is met only in part.

The service is projects/ores.refdata/core/src/service/bundle_import_operations_service.cpp and the messages are in ores.refdata.api/messaging/bundle_import_operations_protocol.hpp. The tables are created by projects/ores.sql/create/refdata/refdata_create.sql, which includes the four files for the import and its items.

Verified by reading the merged files this session. The suite under the [bundle_import] tag covers the dispatch only. The transaction and retry behaviour is unproven by test.

Emacs 29.3 (Org mode 9.6.15)