Catalogue drift review workflow
Date: 2026-09-13
Why this slice exists
Bearing can now observe provider-native and OpenRouter catalogue drift, but an attention status by itself is not enough. The admin needs a safe way to see exactly what changed and deliberately accept metadata updates without allowing a catalogue outage or disappearance to silently alter routing behaviour.
This slice adds the first review/accept loop.
Behaviour
The admin model list links to /admin/catalogue-review.
The review page re-fetches live catalogue evidence and turns disagreements into field-level proposals for:
- input price;
- output price;
- context window;
- externally observable capabilities.
Provider-native metadata wins for fields a provider catalogue actually exposes. OpenRouter fills broader pricing and capability gaps. Capabilities Bearing curates but the external sources cannot observe are preserved.
Availability is intentionally separate. A provider/OpenRouter disappearance is shown as an availability concern, but there is no automatic deactivation or one-click acceptance that changes active state.
Accepting drift
The browser submits only the model slug and selected field names. Proposed values are never trusted from the client.
Before applying a change the server:
- checks the user is an admin;
- re-fetches current provider/OpenRouter evidence;
- rebuilds the current drift proposal;
- applies only fields that are both selected and still drifting;
- resets catalogue confidence to
unknownwhile the row changes; - runs catalogue verification again.
If the re-verification source fails after the accepted update, Bearing remains safely at unknown rather than retaining a stale attention observation against metadata that has already changed.
Mapping preservation fix
The generic model upsert previously set openrouter_id = EXCLUDED.openrouter_id. Editorial admin forms do not carry catalogue IDs, so a normal edit could overwrite an existing mapping with null.
Generic upserts now use:
openrouter_id = COALESCE(EXCLUDED.openrouter_id, models.openrouter_id)
Intentional mapping changes and clears remain the responsibility of the dedicated external-ID persistence path.
Next steps
- Capture reviewer/audit history rather than only the latest verification state.
- Add a deliberate keep-current / dismiss-with-reason path for differences that Bearing chooses not to adopt.
- Expand provider metadata adapters where first-party APIs expose pricing or richer capability metadata.
- Add runtime routability canaries so catalogue presence and actual executable availability are tracked separately.
- Use the reviewed freshness/evidence layer when redesigning alternatives, challenger selection and task-relative capability scoring.