Task: Provision the FOMC meeting schedule into every tenant
Table of Contents
This page documents a task in the Rewrite the oresmd grammar as a hand-written codec checked against ORE story. It captures the goal, current status, acceptance, and any notes or results.
1. Goal
A new tenant resolves the FOMC tenors 1F to 8F to FOMC meeting dates, as the system tenant does, so the synthetic USD-SOFR-FOMC curve feed publishes its pillars.
2. Status
| Field | Value |
|---|---|
| State | DONE |
| Parent story | Rewrite the oresmd grammar as a hand-written codec checked against ORE |
| Now | Nothing. |
| Waiting on | Nothing. |
| Next | Nothing. |
| Last touched | 2026-10-04 |
3. Acceptance
- A new tenant's tenor convention resolutions carry their schedule_code and schedule_step_count once its base datasets are published.
- A new tenant has the US.FOMC calendar, the central_bank_meeting diary entry type and the central_bank_meeting calendar events.
- A new tenant has the ROLL_QUARTER and FOMC_MEETING tenor schedules, so the CREDIT_CDS_IMM and RATES_SPOT_FOMC resolutions keep their schedules.
- A test resolves 1F in a newly provisioned tenant and gets the first FOMC meeting on or after spot.
- On a live run, the USD-SOFR-FOMC feed publishes ticks for its bound parties.
4. Plan
Decided with the owner on 2026-10-04: the chain reaches a tenant by dataset publish, as calendars already do. Lookup vocabulary is copied at provisioning; market reference data is published.
- The provisioner copies the diary entry types. They are vocabulary with no dependencies, as the calendar names and tenor kinds it already copies are.
- The
refdata.calendarsdataset gainsUS.FOMC, so the calendar publish brings it after the countries. - A new dataset,
refdata.tenor_schedules, publishesROLL_QUARTERandFOMC_MEETINGand depends onrefdata.calendars. Its publish function also writes the system tenant'sschedule_codeandschedule_step_countonto the tenant's resolution rows, because those columns can only be set once the schedules exist. The provisioner keeps copying the resolutions without them. - A new dataset,
refdata.calendar_events, publishes the meeting dates and depends onrefdata.calendars. - Both datasets join the
basebundle afterrefdata.calendars, with their artefact types and publish subjects registered. - A database test provisions a tenant, publishes the chain, and resolves
1Fto the first meeting on or after spot. - A live ACME run shows the
usdsofrfomcfeed publishing.
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 |
|---|---|---|---|
| Resolutions given a schedule in a probe tenant, after the chain is published | 14 (6 CREDIT_CDS_IMM, 8 RATES_SPOT_FOMC) |
scratchpad/fomc_chain.sql through psql, in a transaction rolled back |
1d31b32a32 |
| Rows a second publish of the chain rewrites | 2 schedules, 24 events, 0 resolutions | the same script | 1d31b32a32 |
| Sources with a first tick in a live ACME run | 34 of 34, 170 first ticks, 0 drops, 0 publish failures | journalctl on the marketdata and synthetic units |
b4c9634528 |
replace_all on both datasets in a probe tenant with one stray event |
24 of 24 event ids kept, the stray event closed, 2 schedules live, 14 resolutions scheduled | scratchpad/replace_all_probe.sql through psql, rolled back |
review round 1 |
| Test failures with the resolution update removed from the publish | 5 checks fail, every FOMC date resolves to 2026-10-04 | the publish function loaded without its resolution insert, then compass test run -R ores.synthetic.core |
b4c9634528 |
6. Notes
6.1. The cause
The feed synthetic.2026realistic.usdsofrfomc has published nothing in a
provisioned tenant since at least 2026-08-12. Its template starts with the
pillar SPOT to 1F, and 1F to 8F are SPECIAL tenors of the convention
RATES_SPOT_FOMC. A resolution row of that convention names the schedule
FOMC_MEETING and a step count, so 1F is the first meeting on or after spot.
On 2026-10-04, a database query found that the system tenant has these rows,
but the ACME tenant has the rows without schedule_code and
schedule_step_count. The provisioner's copy in
projects/ores.sql/create/iam/iam_tenant_provisioner_create.sql does not list
the two columns. A row with neither column falls back to the calendar axis,
which is spot plus the row's offset. The offset is DAY 0, so in the tenant
every FOMC tenor resolves to spot. The first pillar then has zero length.
Before the market tick change, the curve pricer refused it with "year_fraction
must be positive". After that change, make_pillar_quote_key refuses it first.
The cause is the same.
The provisioner also copies no calendar events, and row security on
ores_refdata_calendar_events_tbl shows a tenant only its own rows. So after
the columns are fixed, the resolver finds no meeting dates and stops with "no
event-lookup dates were supplied". Both gaps must close.
The events cannot simply be copied. The insert trigger of
ores_refdata_calendar_events_tbl checks that the tenant has the event's
calendar and its diary entry type. On 2026-10-04 the ACME tenant had 60 of the
system tenant's 61 calendars, all but US.FOMC, because its calendars come
from a dataset publish rather than the provisioner. It had no diary entry
types, because nothing copies them. So the tenant also needs US.FOMC and
central_bank_meeting before its meeting dates.
No pillar check stops a curve from publishing past data. A curve's dates are calculated from its own as-of date, and only a pillar of zero length from spot is refused.
6.2. The dependency chain
Each step's insert trigger checks the step before it, in the same tenant:
- countries, which a tenant gets only from a dataset publish, after provisioning;
- the
US.FOMCcalendar, whose trigger checks its country; - the diary entry type
central_bank_meeting, which nothing copies; - the tenor schedule
FOMC_MEETING, which checks the calendar and the diary entry type; - the resolution rows'
schedule_code, which checks the tenor schedule; - the meeting dates, which check the calendar and the diary entry type.
The provisioner runs before the publish, so it cannot create step 2. It copies
no tenor schedules either, so ROLL_QUARTER is missing too, and the
CREDIT_CDS_IMM resolutions lose their schedule in the same way as the FOMC
ones.
6.3. What was built
- The provisioner copies the diary entry types.
refdata.calendarscarriesUS.FOMC.refdata.tenor_schedulesandrefdata.calendar_eventsare new datasets in thebasebundle. Both depend onrefdata.calendars. Their artefact tables are generated from thetenor_scheduleandcalendar_eventmodels, and their seeds copy the system tenant's own rows, so the schedules and the meeting dates are listed once.- The calendar event publish matches events on calendar, date and diary entry type. A tenant's event keeps its own id.
- The tenor schedule publish sets the schedule columns of the tenant's resolutions from the system tenant's rows. A second publish changes none of them.
6.4. Captures this task replaces
Two inbox captures described this failure with a wrong cause, a meeting on today's date or a meeting before the valuation date. They were removed when this task was added.
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 |
|---|---|
| #2625 | [refdata] Publish the FOMC meeting schedule to every tenant |
9. Review
| # | Comment summary | File | Decision | Notes |
|---|---|---|---|---|
| 1 | PR 2625: replace_all on calendar events closes every row first, so every event gets a new id. |
refdata_publish_from_dq_create.sql |
Accepted | replace_all closes only the events the dataset does not carry, after the upsert; ids stay. The close uses clock_timestamp(), because a row written earlier in the transaction has a clock valid_from later than current_timestamp. |
| 2 | PR 2625: the resolution update ignores insert_only. |
refdata_publish_from_dq_create.sql |
Accepted | It runs in every mode by design, because the columns are derived and a tenant has no other source; a comment says so. |
| 3 | PR 2625: the update reads the system tenant's resolutions, not the artefact. | refdata_publish_from_dq_create.sql |
Not changed | By design: the dataset seeds copy the same system rows, and the resolutions are system vocabulary copied at provisioning. |
| 4 | PR 2625: replace_all on tenor schedules closes them before the reinsert. |
refdata_publish_from_dq_create.sql |
Accepted | As 1: only the schedules the dataset does not carry are closed, after the upsert. |
| 5 | PR 2625: the test uses std::pair without <utility>. |
feeds_fomc_curve_resolution_tests.cpp |
Accepted | Included. |
| 6 | PR 2625: comment the test's concatenated SQL. | feeds_fomc_curve_resolution_tests.cpp |
Not changed | The names come from a fixed list in the same loop. |
| 7 | PR 2625: the generated artefact header carries org links. | dq_tenor_schedules_artefact_create.sql |
Not changed | Every artefact table gets its header from the model description through the shared template. |
10. Result
A new tenant now resolves the FOMC tenors to meeting dates, and the
usdsofrfomc feed publishes. The calendar, the schedules and the meeting dates
reach a tenant by dataset publish, after its countries, and the schedule publish
completes the resolutions. The CREDIT_CDS_IMM resolutions had lost
ROLL_QUARTER in every tenant in the same way and have it back.
feeds_fomc_curve_resolution_tests.cpp proves it on a tenant of its own, and
fails, with every date on spot, when the resolution update is removed.