Why
The current architecture sketch implies two parallel orchestrator crates (medcare-bridge, smb-bridge) that each glue consumer types to the triplet graph. That shape does not scale: every new consumer (callcenter Supabase transcode, future verticals) would either spawn yet another bridge crate or get force-fitted into one of the existing two, both of which leak consumer-specific types into the bridge layer.
Collapse the two-bridge picture into one thin orchestrator: many Spine impls living in their owner crates, plus ONE unified-bridge crate that knows how to register and project them. The bridge contains zero consumer types; it only depends on lance-graph-contract (the Spine trait + TripletGraph).
The trap to call out for reviewers: this crate must NOT accumulate consumer-specific code. If anyone proposes adding pub struct MedicalRecord or pub struct Invoice here, fix the dep graph; do not pollute the bridge.
What
A new workspace crate (proposed path: crates/lance-graph-bridge/) that is the single orchestrator for all Spine impls in the lance-graph universe.
Surface (initial):
- Registry of
Spine impls. Two viable mechanisms; pick whichever is cheaper to land first:
- Compile-time: trait-bound generics / a
&[&dyn Spine] slice passed by the caller.
- Runtime:
inventory crate or ctor macro auto-registration. Neither is currently a workspace dep — pick whichever requires the smallest delta.
- Unified projection API:
bridge::project_all(impls: &[&dyn Spine]) -> TripletGraph.
- Health/status surface: which impls are registered, round-trip pass rate, last error per impl.
- Smoke harness: two trivial fake
Spine impls (FakeColor, FakeShape) baked into the crate's tests so the registry + round-trip path can be validated without depending on any real consumer.
Architecture
lance-graph-contract <-- Spine trait, TripletGraph (A1)
^ ^
| |
lance-graph-bridge consumer crates (medcare, smb, callcenter, ...)
(THIS ISSUE) each owns its own Spine impl
^
|
downstream apps call bridge::project_all(&[&medcare_spine, &smb_spine, ...])
Key invariants:
lance-graph-bridge/Cargo.toml depends on lance-graph-contract only. No medcare, no smb, no callcenter deps.
- The crate compiles standalone in the workspace with zero consumer crates present.
- Consumer-specific types never appear in the bridge's public API.
- Replaces the conceptual
medcare-bridge and smb-bridge orchestrators — those are not separate crates; they are Spine impls inside their owner crates.
Acceptance criteria
Out of scope
- Real consumer
Spine impls (medcare, smb) — those are tracked under B2 / B3.
- callcenter Supabase transcode — that is a separate consumer
Spine impl, not the bridge.
- Materialization backends (Lance, parquet, etc.) — the bridge returns
TripletGraph; persistence is downstream.
- Any consumer type definition. If a PR for this issue adds consumer structs, it should be rejected.
Dependencies
- Blocks on A1:
Spine trait + TripletGraph must exist on lance-graph-contract. This issue cannot land until A1 is merged. Once A1 is in, this scaffold is mechanical.
Why
The current architecture sketch implies two parallel orchestrator crates (medcare-bridge, smb-bridge) that each glue consumer types to the triplet graph. That shape does not scale: every new consumer (callcenter Supabase transcode, future verticals) would either spawn yet another bridge crate or get force-fitted into one of the existing two, both of which leak consumer-specific types into the bridge layer.
Collapse the two-bridge picture into one thin orchestrator: many
Spineimpls living in their owner crates, plus ONEunified-bridgecrate that knows how to register and project them. The bridge contains zero consumer types; it only depends onlance-graph-contract(theSpinetrait +TripletGraph).The trap to call out for reviewers: this crate must NOT accumulate consumer-specific code. If anyone proposes adding
pub struct MedicalRecordorpub struct Invoicehere, fix the dep graph; do not pollute the bridge.What
A new workspace crate (proposed path:
crates/lance-graph-bridge/) that is the single orchestrator for allSpineimpls in the lance-graph universe.Surface (initial):
Spineimpls. Two viable mechanisms; pick whichever is cheaper to land first:&[&dyn Spine]slice passed by the caller.inventorycrate orctormacro auto-registration. Neither is currently a workspace dep — pick whichever requires the smallest delta.bridge::project_all(impls: &[&dyn Spine]) -> TripletGraph.Spineimpls (FakeColor,FakeShape) baked into the crate's tests so the registry + round-trip path can be validated without depending on any real consumer.Architecture
Key invariants:
lance-graph-bridge/Cargo.tomldepends onlance-graph-contractonly. No medcare, no smb, no callcenter deps.medcare-bridgeandsmb-bridgeorchestrators — those are not separate crates; they areSpineimpls inside their owner crates.Acceptance criteria
crates/lance-graph-bridge/(or equivalent) exists and is added to the workspacemembersin the rootCargo.toml.Cargo.tomllistslance-graph-contractas the only first-party dep. No consumer crates.inventory/ctor).project_all(impls: &[&dyn Spine]) -> TripletGraph(or equivalent signature once A1 lands).Spineimpls (FakeColor,FakeShape) intests/or#[cfg(test)]that:project_all.verify_roundtripfor each.cargo build -p lance-graph-bridgeandcargo test -p lance-graph-bridgepass without any consumer crate in the build graph.Out of scope
Spineimpls (medcare, smb) — those are tracked under B2 / B3.Spineimpl, not the bridge.TripletGraph; persistence is downstream.Dependencies
Spinetrait +TripletGraphmust exist onlance-graph-contract. This issue cannot land until A1 is merged. Once A1 is in, this scaffold is mechanical.