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_tblandores_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
\irline 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 familychecks. The transaction behaviour has no test of its own, so the rollback claim rests on theunit_of_workdestructor and not on a test. commit_bundle_import_responsedeclaresfx_skippedand 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
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.