Story: Import and export conventions without a document aggregate

Table of Contents

This page documents a story in Sprint 30, carried unfinished from Sprint 28 at close. It captures the goal, current status, acceptance criteria, and the tasks that compose it.

1. Goal

A conventions import and export carries each convention family as its own typed message. A new convention adds a family and does not grow a document aggregate. The staging and the atomic apply are merged (#3462 to #3485). What remains is the typed path: the ORE package, the export and the stage messages still use untyped JSON.

2. Status

Field Value
State BACKLOG
Parent sprint Sprint 30
Now Not yet started.
Waiting on Nothing.
Next Break the story into tasks.
Last touched 2026-11-08

3. Acceptance

  • Each convention family is staged by a generated message that carries the family's value type.
  • The transient conventions package holds typed rows and not JSON strings.
  • The export reads each family through its generated list request at one instant.
  • ores.ore has no untyped rfl::Generic read of a convention.

4. Tasks

Task State Start End Description
Generate a typed view of the convention family registry BACKLOG     Generate, beside the string registry, a compile-time list of every convention family's value type and protocol, so a caller can visit each family with its own types.
Stage each convention family as a typed message BACKLOG     Replace the generic stage request, which carries a family name and the row as a JSON string, with one generated stage message per family that carries the family's own value type.
Export conventions through the typed family reads BACKLOG     Read each convention family through its generated list request at one instant and for the run's party, in place of the untyped rfl::Generic reads in ores.ore.
Hold the conventions package as typed rows in ores.ore BACKLOG     Keep the transient conventions package inside ores.ore as typed family rows, not JSON strings, so the mapper, the joins and the diff work on values.

5. Decisions

  • Pull requests merged in sprint 28 for this work, with no task to record them: #3462, #3465, #3467, #3469, #3474, #3475, #3481, #3482 and #3485. They stage a conventions import in two tables, apply it in one transaction, move the ORE path onto it, and rename the staging to bundle import. The story was carried with no task. The next owner should write the tasks and close the ones these PRs finished.
  • 2026-11-02: the code drifted from the design into untyped data in three places. The stage message carries a family name and the row as a JSON string, where the design asks for one typed stage per family. The export reads each family through rfl::Generic, with a hand-built request, the first array of the reply and a party filter in ores.ore, and a null as_of. Inside ores.ore the package holds rows as JSON strings. The cause is that the registry is a table of strings, so only refdata's generated apply could dispatch on it. A typed view of the registry is the first task, and the other three build on it. A typed transient package inside ores.ore is allowed; one struct with a typed array per kind on the wire is not.
  • Goal and acceptance written on 2026-11-08 at sprint 30 start. They were still placeholders. They overlap the sqlgen and reflect-cpp story, which removes the same rfl::Generic reads, so these two must be sequenced.

6. Out of scope

Emacs 29.3 (Org mode 9.6.15)