Skip to content

Commit 2decb2f

Browse files
committed
feat(ogar/bridges): WoaBridge + SmbBridge + OdooBridge — close the planner→ERP convergence chain
Operator value statement 2026-06-21: "in the end planning (openproject) and ERP (odoo, YOU) should become reusable ontologies so that the planner times can align with billable hours". OGAR PR #93 (WoaPort + SmbPort) and PR #94 (OdooPort) landed the canonical port specs; this PR ships the lance-graph-side type aliases that connect those ports to the existing `UnifiedBridge<P: PortSpec>` harness. Three new files, all ~150 LOC each, all following the medcare_bridge.rs template: - WoaBridge = UnifiedBridge<ogar_vocab::ports::WoaPort> (NAMESPACE "WorkOrder", bridge_id "woa"). Customer/Kunde resolves to BILLING_PARTY (0x0204); Vorgang/WorkOrder/Quote/Invoice/CreditNote to COMMERCIAL_DOCUMENT (0x0202); Position/LineItem to COMMERCIAL_LINE_ITEM (0x0201); TaxRate/Steuersatz to TAX_POLICY (0x0203); Payment/Zahlung to PAYMENT_RECORD (0x0205); Stundenzettel/ TimesheetActivity/TimeEntry/Zeiterfassung to BILLABLE_WORK_ENTRY (0x0103). - SmbBridge = UnifiedBridge<ogar_vocab::ports::SmbPort> (NAMESPACE "SMB", bridge_id "smb"). Same canonical block as WoA — Kunde→ BILLING_PARTY, Stundenzettel→BILLABLE_WORK_ENTRY, etc. — so smb-office-rs gets cross-fork convergence with WoA + OpenProject + Odoo for free. - OdooBridge = UnifiedBridge<ogar_vocab::ports::OdooPort> (NAMESPACE "Odoo", bridge_id "odoo"). Odoo's Python class names (res.partner / account.move / account.move.line / hr.attendance / …) resolve to the same canonical block. Closes the planner→ERP→billing chain at every hop. The convergence pin (the operator's value statement as a bridge-side test): - `bridges::woa_bridge::tests::entity_resolves_stundenzettel_to_ billable_work_entry_planner_convergence` ✓ - `bridges::smb_bridge::tests::entity_resolves_stundenzettel_to_ billable_work_entry_planner_convergence` ✓ Both assert that `bridge.entity("Stundenzettel").schema_ptr. entity_type_id() == 0x0103 BILLABLE_WORK_ENTRY`, the SAME id `OpenProjectBridge.entity("TimeEntry")` and `RedmineBridge. entity("TimeEntry")` return. The planner→ERP integration is now a codebook lookup, not a translation layer. Tests: 53/53 lance-graph-ogar lib tests pass, including the 14 new tests (5 per bridge minus 1 missing in odoo). Cargo lock updated to pull OGAR main @ 08a9c979 (post #93+#94 merge). Unrelated drive-by: cargo fmt picked up minor formatting nits in unified.rs / medcare_bridge.rs / openproject_bridge.rs / tests/ bridge_codebook_convergence.rs — included to keep the tree fmt-clean. Pre-existing clippy `--lib -- -D warnings` errors in lance-graph- ontology and the OGAR bridges (8 `dead_code` warnings on the per- bridge `pub const NAMESPACE` constants — pre-migration compat shims that aren't used inside the crate) are NOT introduced by this PR and affect medcare_bridge.rs / openproject_bridge.rs / redmine_bridge.rs identically — the new bridges follow the same pattern. Consumer-side migrations queued (next, in their own repos): - woa-rs: RFC-010 (Iron Rule 1 allow-list: add `lance-graph-ogar`) + switch `use lance_graph_ontology::bridges::WoaBridge` → `use lance_graph_ogar::bridges::WoaBridge` across 4 files (~50 LOC). - smb-office-rs: Cargo dep + repoint `crates/smb-bridge/src/unified_bridge_wiring.rs` from `OgitBridge` to `SmbBridge` (~50 LOC). - odoo-rs / openproject-nexgen-rs: their own sessions per the medcare-rs #168 worked example pattern. Cross-refs: OGAR PR #93 (WoaPort + SmbPort, merged), OGAR PR #94 (OdooPort, merged), lance-graph PR #585 (the OGIT/OGAR separation that gated this work), EPIPHANIES `E-OGAR-AR-MIGRATION-IS-SEVERITY`, ISSUES `OGAR-AR-MIGRATION-WOA-SMB-OPEN`, woa-rs `.claude/board/OGAR-MIGRATION-GAP-2026-06-21.md`, smb-office-rs `.claude/board/TECH_DEBT.md` `TD-OGAR-CONSUMER-MIGRATION-1`. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xzyc27Nx3f8WC5KzwfWfjx
1 parent fc7b2c9 commit 2decb2f

9 files changed

Lines changed: 1047 additions & 682 deletions

File tree

Cargo.lock

Lines changed: 583 additions & 664 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/lance-graph-ogar/src/bridges/medcare_bridge.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ use crate::bridges::unified::UnifiedBridge;
2828
// `HealthcarePort::NAMESPACE` / `::aliases()` are `PortSpec` associated
2929
// items — the trait must be in scope for the resolution to work (codex
3030
// P1 on PR #570). Same import in the test module below.
31-
use ogar_vocab::ports::PortSpec;
3231
pub use ogar_vocab::ports::HealthcarePort;
32+
use ogar_vocab::ports::PortSpec;
3333

3434
/// MedCare `NamespaceBridge` — alias over the generic harness, locked to
3535
/// the `Healthcare` namespace via [`HealthcarePort`].

crates/lance-graph-ogar/src/bridges/mod.rs

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
//! `ogar_vocab::class_ids` (the OGAR codebook + `PortSpec` class schema),
66
//! so they live here in `lance-graph-ogar`, NOT in `lance-graph-ontology`
77
//! (which is OGIT and must not depend on `ogar-vocab`). The OGIT-side
8-
//! legacy bridges (`WoaBridge` / `SpearBridge` / `SharePointBridge` /
9-
//! `OgitBridge`) stay in `lance_graph_ontology::bridges`.
8+
//! legacy bridges (`SpearBridge` / `SharePointBridge` / `OgitBridge` +
9+
//! the legacy `WoaBridge` pass-through) stay in
10+
//! `lance_graph_ontology::bridges`.
1011
//!
1112
//! # Two layers
1213
//!
@@ -17,7 +18,8 @@
1718
//! `ogar_vocab::ports::PortSpec`. Adding a port is `impl PortSpec for
1819
//! FooPort {…}` in OGAR — no bridge boilerplate here.
1920
//! - The **per-port aliases** ([`OpenProjectBridge`], [`RedmineBridge`],
20-
//! [`MedcareBridge`]) are thin `type` aliases over the harness.
21+
//! [`MedcareBridge`], [`WoaBridge`], [`SmbBridge`], [`OdooBridge`]) are
22+
//! thin `type` aliases over the harness.
2123
//!
2224
//! # OGAR-driven ports (`UnifiedBridge<P>` aliases)
2325
//!
@@ -28,23 +30,46 @@
2830
//! - [`RedmineBridge`]: `UnifiedBridge<ogar_vocab::ports::RedminePort>` —
2931
//! locks to the `Redmine` namespace. `Issue` / `TimeEntry` / `Project`
3032
//! etc. resolve to the SAME OGAR canonical class_ids as the
31-
//! OpenProject equivalents, so cross-fork convergence is the default
32-
//! not the exception.
33+
//! OpenProject equivalents.
3334
//! - [`MedcareBridge`]: `UnifiedBridge<ogar_vocab::ports::HealthcarePort>`
3435
//! — locks to the `Healthcare` namespace. `Patient` / `Diagnosis` /
3536
//! `LabValue` / `Medication` / `Treatment` / `Visit` / `VitalSign`
3637
//! resolve to the `0x09XX` Health codebook (Northstar T9).
38+
//! - [`WoaBridge`]: `UnifiedBridge<ogar_vocab::ports::WoaPort>` — locks
39+
//! to the `WorkOrder` namespace. `Customer` / `Vorgang` / `Position` /
40+
//! `Stundenzettel` / `TimesheetActivity` / `TimeEntry` etc. resolve to
41+
//! the canonical commerce `0x02XX` block + `BILLABLE_WORK_ENTRY`
42+
//! (0x0103). The planner-side `TimeEntry` (OpenProject/Redmine) and
43+
//! the WoA `Stundenzettel` collapse to the same id — the operator's
44+
//! *"planner times align with billable hours"* statement realised as
45+
//! data.
46+
//! - [`SmbBridge`]: `UnifiedBridge<ogar_vocab::ports::SmbPort>` — locks
47+
//! to the `SMB` namespace. `Kunde` / `Auftrag` / `Rechnung` /
48+
//! `Stundenzettel` etc. resolve to the SAME commerce block + same
49+
//! `BILLABLE_WORK_ENTRY`, giving smb-office-rs cross-fork convergence
50+
//! with WoA + OpenProject + Odoo.
51+
//! - [`OdooBridge`]: `UnifiedBridge<ogar_vocab::ports::OdooPort>` —
52+
//! locks to the `Odoo` namespace. Odoo's Python class names
53+
//! (`res.partner` / `account.move` / `account.move.line` /
54+
//! `hr.attendance` / …) resolve to the same canonical block.
55+
//! Closes the planner→ERP→billing convergence chain at every hop.
3756
3857
pub mod unified;
3958

4059
mod medcare_bridge;
60+
mod odoo_bridge;
4161
mod openproject_bridge;
4262
mod redmine_bridge;
63+
mod smb_bridge;
64+
mod woa_bridge;
4365

4466
pub use medcare_bridge::{HealthcarePort, MedcareBridge};
67+
pub use odoo_bridge::{OdooBridge, OdooPort};
4568
pub use openproject_bridge::{OpenProjectBridge, OpenProjectPort};
4669
pub use redmine_bridge::{RedmineBridge, RedminePort};
70+
pub use smb_bridge::{SmbBridge, SmbPort};
4771
pub use unified::UnifiedBridge;
72+
pub use woa_bridge::{WoaBridge, WoaPort};
4873

4974
// Compatibility shims for the pre-migration constants. `bridges`
5075
// previously re-exported `OPENPROJECT_CODEBOOK` / `REDMINE_CODEBOOK`
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
//! Odoo (ERP) tenant bridge — thin type alias over
2+
//! [`crate::bridges::unified::UnifiedBridge`] parameterised by
3+
//! [`ogar_vocab::ports::OdooPort`].
4+
//!
5+
//! Odoo's OGAR-driven port surface (OGAR PR #94, 2026-06-21). Companion
6+
//! to the [`lance_graph_supervisor::actors::OdooConsumerActor`]
7+
//! skeleton (lance-graph activation profile, supervisor slot G=50) and
8+
//! the four-way alignment seam in
9+
//! `lance_graph_callcenter::odoo_alignment` (Seam decision 1 /
10+
//! Option B — odoo inherits FIBO/SKR family slots via
11+
//! `owl:equivalentClass` routing; no new CAM codebook family minted).
12+
//!
13+
//! # The convergence pin (operator value statement 2026-06-21)
14+
//!
15+
//! Odoo's `HrAttendance` and `account.move.line(qty=hours)` resolve to
16+
//! the SAME canonical [`ogar_vocab::class_ids::BILLABLE_WORK_ENTRY`]
17+
//! the planner consumers (OpenProject `TimeEntry`, Redmine `TimeEntry`)
18+
//! and the German ERP consumers (WoA `Stundenzettel`, SMB
19+
//! `Stundenzettel`) all resolve to. The planner→ERP→billing chain
20+
//! collapses into one codebook lookup at every hop.
21+
22+
use crate::bridges::unified::UnifiedBridge;
23+
pub use ogar_vocab::ports::OdooPort;
24+
use ogar_vocab::ports::PortSpec;
25+
26+
/// Odoo `NamespaceBridge` — alias over the generic harness, locked to
27+
/// the `Odoo` namespace via [`OdooPort`].
28+
pub type OdooBridge = UnifiedBridge<OdooPort>;
29+
30+
/// Canonical namespace name for Odoo. Mirrors `OdooPort::NAMESPACE`.
31+
pub const NAMESPACE: &str = OdooPort::NAMESPACE;
32+
33+
#[cfg(test)]
34+
mod tests {
35+
use super::*;
36+
use lance_graph_ontology::bridge::{BridgeError, NamespaceBridge};
37+
use lance_graph_ontology::error::Error;
38+
use lance_graph_ontology::namespace::NamespaceId;
39+
use lance_graph_ontology::registry::OntologyRegistry;
40+
use ogar_vocab::ports::PortSpec;
41+
use std::fs;
42+
use std::sync::Arc;
43+
44+
fn registry_with_odoo() -> Arc<OntologyRegistry> {
45+
let ttl = r#"
46+
@prefix ogit: <http://www.purl.org/ogit/> .
47+
@prefix ogit.Odoo: <http://www.purl.org/ogit/Odoo/> .
48+
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
49+
50+
ogit.Odoo:Partner
51+
a rdfs:Class;
52+
rdfs:subClassOf ogit:Entity;
53+
rdfs:label "Partner";
54+
ogit:scope "NTO";
55+
ogit:parent ogit:Node;
56+
ogit:mandatory-attributes ( ogit:id );
57+
ogit:optional-attributes ( ) ;
58+
.
59+
"#;
60+
let tmp = tempfile::tempdir().unwrap();
61+
fs::create_dir_all(tmp.path().join("Odoo")).unwrap();
62+
fs::write(tmp.path().join("Odoo").join("ents.ttl"), ttl).unwrap();
63+
let registry = Arc::new(OntologyRegistry::new_in_memory());
64+
registry.hydrate_once_sync(tmp.path(), &["Odoo"]).unwrap();
65+
registry
66+
}
67+
68+
#[test]
69+
fn new_succeeds_when_namespace_registered() {
70+
let registry = registry_with_odoo();
71+
let bridge = OdooBridge::new(registry).unwrap();
72+
assert_ne!(bridge.g_lock(), NamespaceId::UNKNOWN);
73+
}
74+
75+
#[test]
76+
fn new_returns_unknown_namespace_when_not_registered() {
77+
let registry = Arc::new(OntologyRegistry::new_in_memory());
78+
match OdooBridge::new(registry) {
79+
Ok(_) => panic!("expected UnknownNamespace, got Ok(_)"),
80+
Err(Error::UnknownNamespace(name)) => assert_eq!(name, "Odoo"),
81+
Err(other) => panic!("expected UnknownNamespace, got {other:?}"),
82+
}
83+
}
84+
85+
#[test]
86+
fn bridge_id_is_lowercase_odoo() {
87+
let bridge = OdooBridge::new(registry_with_odoo()).unwrap();
88+
assert_eq!(bridge.bridge_id(), "odoo");
89+
}
90+
91+
#[test]
92+
fn entity_for_each_codebook_entry_returns_its_canonical_class_id() {
93+
let bridge = OdooBridge::new(registry_with_odoo()).unwrap();
94+
for &(public_name, expected_id) in OdooPort::aliases() {
95+
let entity = bridge.entity(public_name).unwrap_or_else(|e| {
96+
panic!("codebook entry `{public_name}` failed to resolve: {e:?}")
97+
});
98+
assert_eq!(
99+
entity.schema_ptr.entity_type_id(),
100+
expected_id,
101+
"codebook entry `{public_name}` should resolve to 0x{expected_id:04X}",
102+
);
103+
}
104+
}
105+
106+
#[test]
107+
fn entity_for_non_codebook_name_falls_back_to_registry_lookup() {
108+
let bridge = OdooBridge::new(registry_with_odoo()).unwrap();
109+
match bridge.entity("NotAConcept") {
110+
Err(BridgeError::NotInScope { public_name, .. }) => {
111+
assert_eq!(public_name, "NotAConcept")
112+
}
113+
other => panic!("expected NotInScope, got {other:?}"),
114+
}
115+
}
116+
}

crates/lance-graph-ogar/src/bridges/openproject_bridge.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ use crate::bridges::unified::UnifiedBridge;
1818
// `OpenProjectPort::NAMESPACE` / `::aliases()` are `PortSpec`
1919
// associated items — the trait must be in scope for the resolution to
2020
// work (codex P1 on PR #570). Same import in the test module below.
21-
use ogar_vocab::ports::PortSpec;
2221
pub use ogar_vocab::ports::OpenProjectPort;
22+
use ogar_vocab::ports::PortSpec;
2323

2424
/// OpenProject `NamespaceBridge` — alias over the generic harness.
2525
pub type OpenProjectBridge = UnifiedBridge<OpenProjectPort>;
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
//! SMB (small-and-medium-business German office ERP) tenant bridge —
2+
//! thin type alias over [`crate::bridges::unified::UnifiedBridge`]
3+
//! parameterised by [`ogar_vocab::ports::SmbPort`].
4+
//!
5+
//! SMB's OGAR-driven port surface (OGAR PR #93, 2026-06-21). The legacy
6+
//! OGIT-side [`lance_graph_ontology::bridges::OgitBridge`] (pass-through
7+
//! for raw OGIT URIs) stays in place for tools that don't need codebook
8+
//! synthesis; this OGAR-side bridge gives smb-office-rs cross-fork
9+
//! convergence with WoA + OpenProject + Odoo on the canonical class_ids.
10+
//!
11+
//! # The convergence pin (operator value statement 2026-06-21)
12+
//!
13+
//! SMB's `Stundenzettel` / `TimeEntry` / `Zeiterfassung` resolve to
14+
//! [`ogar_vocab::class_ids::BILLABLE_WORK_ENTRY`] via this bridge's
15+
//! `entity()` codebook synthesis path — the SAME id WoA's Stundenzettel,
16+
//! OpenProject's TimeEntry, and Odoo's HrAttendance / account.move.line
17+
//! (qty=hours) resolve to. *"Planner times align with billable hours"*
18+
//! becomes a codebook lookup, not a translation layer. See
19+
//! `ogar_vocab::ports::tests::time_entry_converges_across_planner_and_erp_ports`.
20+
21+
use crate::bridges::unified::UnifiedBridge;
22+
use ogar_vocab::ports::PortSpec;
23+
pub use ogar_vocab::ports::SmbPort;
24+
25+
/// SMB `NamespaceBridge` — alias over the generic harness, locked to
26+
/// the `SMB` namespace via [`SmbPort`].
27+
pub type SmbBridge = UnifiedBridge<SmbPort>;
28+
29+
/// Canonical namespace name for SMB. Mirrors `SmbPort::NAMESPACE`.
30+
pub const NAMESPACE: &str = SmbPort::NAMESPACE;
31+
32+
#[cfg(test)]
33+
mod tests {
34+
use super::*;
35+
use lance_graph_ontology::bridge::{BridgeError, NamespaceBridge};
36+
use lance_graph_ontology::error::Error;
37+
use lance_graph_ontology::namespace::NamespaceId;
38+
use lance_graph_ontology::registry::OntologyRegistry;
39+
use ogar_vocab::class_ids;
40+
use ogar_vocab::ports::PortSpec;
41+
use std::fs;
42+
use std::sync::Arc;
43+
44+
fn registry_with_smb() -> Arc<OntologyRegistry> {
45+
let ttl = r#"
46+
@prefix ogit: <http://www.purl.org/ogit/> .
47+
@prefix ogit.SMB: <http://www.purl.org/ogit/SMB/> .
48+
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
49+
50+
ogit.SMB:Kunde
51+
a rdfs:Class;
52+
rdfs:subClassOf ogit:Entity;
53+
rdfs:label "Kunde";
54+
ogit:scope "NTO";
55+
ogit:parent ogit:Node;
56+
ogit:mandatory-attributes ( ogit:id );
57+
ogit:optional-attributes ( ) ;
58+
.
59+
"#;
60+
let tmp = tempfile::tempdir().unwrap();
61+
fs::create_dir_all(tmp.path().join("SMB")).unwrap();
62+
fs::write(tmp.path().join("SMB").join("ents.ttl"), ttl).unwrap();
63+
let registry = Arc::new(OntologyRegistry::new_in_memory());
64+
registry.hydrate_once_sync(tmp.path(), &["SMB"]).unwrap();
65+
registry
66+
}
67+
68+
#[test]
69+
fn new_succeeds_when_namespace_registered() {
70+
let registry = registry_with_smb();
71+
let bridge = SmbBridge::new(registry).unwrap();
72+
assert_ne!(bridge.g_lock(), NamespaceId::UNKNOWN);
73+
}
74+
75+
#[test]
76+
fn new_returns_unknown_namespace_when_not_registered() {
77+
let registry = Arc::new(OntologyRegistry::new_in_memory());
78+
match SmbBridge::new(registry) {
79+
Ok(_) => panic!("expected UnknownNamespace, got Ok(_)"),
80+
Err(Error::UnknownNamespace(name)) => assert_eq!(name, "SMB"),
81+
Err(other) => panic!("expected UnknownNamespace, got {other:?}"),
82+
}
83+
}
84+
85+
#[test]
86+
fn bridge_id_is_lowercase_smb() {
87+
let bridge = SmbBridge::new(registry_with_smb()).unwrap();
88+
assert_eq!(bridge.bridge_id(), "smb");
89+
}
90+
91+
#[test]
92+
fn entity_resolves_kunde_to_canonical_billing_party_class_id() {
93+
let bridge = SmbBridge::new(registry_with_smb()).unwrap();
94+
let entity = bridge.entity("Kunde").unwrap();
95+
assert_eq!(entity.schema_ptr.entity_type_id(), class_ids::BILLING_PARTY);
96+
assert_eq!(entity.schema_ptr.entity_type_id(), 0x0204);
97+
}
98+
99+
#[test]
100+
fn entity_resolves_stundenzettel_to_billable_work_entry_planner_convergence() {
101+
let bridge = SmbBridge::new(registry_with_smb()).unwrap();
102+
for public_name in ["Stundenzettel", "TimeEntry", "Zeiterfassung"] {
103+
let entity = bridge
104+
.entity(public_name)
105+
.unwrap_or_else(|e| panic!("{public_name}: {e:?}"));
106+
assert_eq!(
107+
entity.schema_ptr.entity_type_id(),
108+
class_ids::BILLABLE_WORK_ENTRY,
109+
"SMB `{public_name}` must resolve to BILLABLE_WORK_ENTRY (planner-ERP convergence)",
110+
);
111+
}
112+
}
113+
114+
#[test]
115+
fn entity_for_each_codebook_entry_returns_its_canonical_class_id() {
116+
let bridge = SmbBridge::new(registry_with_smb()).unwrap();
117+
for &(public_name, expected_id) in SmbPort::aliases() {
118+
let entity = bridge.entity(public_name).unwrap_or_else(|e| {
119+
panic!("codebook entry `{public_name}` failed to resolve: {e:?}")
120+
});
121+
assert_eq!(
122+
entity.schema_ptr.entity_type_id(),
123+
expected_id,
124+
"codebook entry `{public_name}` should resolve to 0x{expected_id:04X}",
125+
);
126+
}
127+
}
128+
129+
#[test]
130+
fn entity_for_non_codebook_name_falls_back_to_registry_lookup() {
131+
let bridge = SmbBridge::new(registry_with_smb()).unwrap();
132+
match bridge.entity("Artikel") {
133+
// Artikel/Product/SKU isn't in the codebook yet (intentional —
134+
// needs a `0x02XX` codebook extension). Until then it falls
135+
// through to the registry-resolution path which returns
136+
// NotInScope because the TTL fixture only hydrates `Kunde`.
137+
Err(BridgeError::NotInScope { public_name, .. }) => {
138+
assert_eq!(public_name, "Artikel")
139+
}
140+
other => panic!("expected NotInScope, got {other:?}"),
141+
}
142+
}
143+
}

crates/lance-graph-ogar/src/bridges/unified.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,8 @@ impl<P: PortSpec> UnifiedBridge<P> {
8989
/// on the convergence contract.
9090
fn synthesize_codebook_entity(&self, class_id: u16) -> EntityRef {
9191
let ctx_id = NamespaceRegistry::seed_context_id(P::NAMESPACE).unwrap_or(0);
92-
let schema_ptr = SchemaPtr::new(self.g_lock, class_id, SchemaKind::Entity)
93-
.with_context_id(ctx_id);
92+
let schema_ptr =
93+
SchemaPtr::new(self.g_lock, class_id, SchemaKind::Entity).with_context_id(ctx_id);
9494
EntityRef { schema_ptr }
9595
}
9696
}
@@ -144,13 +144,13 @@ impl<P: PortSpec> NamespaceBridge for UnifiedBridge<P> {
144144
}
145145
}
146146
}
147-
let ptr = self
148-
.registry()
149-
.resolve_uri(uri.as_str())
150-
.ok_or_else(|| BridgeError::NotInScope {
151-
bridge_id: self.bridge_id_static(),
152-
public_name: uri.as_str().to_string(),
153-
})?;
147+
let ptr =
148+
self.registry()
149+
.resolve_uri(uri.as_str())
150+
.ok_or_else(|| BridgeError::NotInScope {
151+
bridge_id: self.bridge_id_static(),
152+
public_name: uri.as_str().to_string(),
153+
})?;
154154
if ptr.namespace_id() != self.g_lock() {
155155
return Err(BridgeError::CrossNamespaceLeak {
156156
bridge_id: self.bridge_id_static(),

0 commit comments

Comments
 (0)