Skip to content

Commit b1ad1b5

Browse files
authored
Merge pull request #603 from AdaWorldAPI/claude/medcare-bridge-lance-graph-wmx76z
contract: retarget CLASSID_FMA 0x0901 → 0x0A01 (clear the FMA/patient classid collision)
2 parents 8bfc933 + 1c6a7db commit b1ad1b5

3 files changed

Lines changed: 68 additions & 15 deletions

File tree

.claude/board/EPIPHANIES.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,29 @@
1+
## 2026-06-24 — E-CLASSID-FMA-PATIENT-COLLISION — `CLASSID_FMA = 0x0901` aliased OGAR `patient`; retargeted to the Anatomy domain `0x0A01`
2+
3+
**Status:** FINDING + FIX (2026-06-24). Surfaced by OGAR's NodeGuid canon audit
4+
(`OGAR/docs/NODEGUID-CANON-AUDIT.md` F-1). `canonical_node.rs` pinned
5+
`NodeGuid::CLASSID_FMA = 0x0000_0901` ("anatomy concept in the Health domain",
6+
ISS-CLASSID-OGAR-DRIFT realign 2026-06-20). But `ogar_codebook.rs` has
7+
`("patient", 0x0901)` — so **FMA anatomy and `patient` shared the identical
8+
classid `0x0901`**, both in Health (`>>8 == 0x09`). A consumer could not tell an
9+
FMA structural node from a patient node by classid; RBAC over `0x0901` (the
10+
patient grants in `rbac.rs`) would also gate FMA reference data.
11+
12+
**Root cause:** anatomy was placed in the Health PHI domain. But anatomy is
13+
**public reference** (the femur exists; it is `part_of` the lower limb) — a
14+
clinical *finding about* it is PHI; the structure itself is not.
15+
16+
**Fix:** OGAR minted a new **Anatomy domain `0x0A`** this week
17+
(`anatomical_structure 0x0A01` / `skeleton 0x0A02` / `bone 0x0A03` / `joint
18+
0x0A04`); this contract mirrors it — `ConceptDomain::Anatomy`, `0x0A` routing,
19+
the four concepts in `CODEBOOK` — and **retargets `CLASSID_FMA 0x0901 → 0x0A01`**
20+
(`anatomical_structure`, the FMA root). `patient` stays at `0x0901`; the
21+
collision is cleared. Constant-following consumers (the `ReadMode::FMA` registry,
22+
`soa_graph` `DomainSpec`, q2 #50's `osint-bake/fma` which uses the constant)
23+
inherit the fix with no change. Tests updated to assert `0x0A01` / Anatomy and to
24+
forbid the `0x0901` alias. Cross-ref: OGAR PR #117 (the Anatomy mint + audit),
25+
q2 PR #50 (independent `[mixin:instance]` convergence, F-6).
26+
127
## 2026-06-23 — E-CLASSRBAC-PROMOTED-TO-CONTRACT — the §11 trait-placement that lets ogar join the RBAC chain
228

329
**Status:** FINDING (2026-06-23). The four-crate chain `contract ↔ rbac ↔ ogar ↔

crates/lance-graph-contract/src/canonical_node.rs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,19 +45,24 @@ impl NodeGuid {
4545
// `canonical_concept_domain(classid_lo)` (see `crate::ogar_codebook`) routes on
4646
// `classid >> 8`. Realigned 2026-06-20 (ISS-CLASSID-OGAR-DRIFT): OSINT was
4747
// 0x0007 (OGAR Reserved domain) → 0x0700; FMA was 0x0008 (OGAR OCR block) →
48-
// 0x0901 (anatomy concept in the Health domain). Migration:
49-
// `.claude/plans/ogar-vocab-contract-codebook-migration-v1.md`.
48+
// 0x0901. Re-realigned 2026-06-24 (ISS-CLASSID-OGAR-DRIFT cont.): FMA 0x0901
49+
// **collided with OGAR `patient` (0x0901)** — both Health. FMA now routes to
50+
// the new **Anatomy** domain root 0x0A01 (`anatomical_structure`); anatomy is
51+
// public reference, not Health PHI. Surfaced by OGAR `docs/NODEGUID-CANON-AUDIT.md`
52+
// F-1. Migration: `.claude/plans/ogar-vocab-contract-codebook-migration-v1.md`.
5053

5154
/// **OSINT / Palantir-Gotham** domain root (`0x07` = OSINT domain, `0x00` =
5255
/// root). The neo4j-emulation entity graph (people / orgs / systems / events,
5356
/// family-grouped). Resolves to [`ReadMode::OSINT`] (hot `Cognitive` value +
5457
/// `CoarseOnly` adjacency).
5558
pub const CLASSID_OSINT: u32 = 0x0000_0700;
56-
/// **FMA anatomy** — the `anatomy` concept (`0x01`) in the **Health** domain
57-
/// (`0x09`); `0x0900` is the Health root. The Foundational Model of Anatomy
59+
/// **FMA anatomy** — `anatomical_structure` (`0x01`) in the **Anatomy** domain
60+
/// (`0x0A`); `0x0A00` is the Anatomy root. The Foundational Model of Anatomy
5861
/// (~70k structural entities, family = body region, bones = stability anchors).
59-
/// Resolves to [`ReadMode::FMA`] (cold `Compressed` reference + `CoarseOnly`).
60-
pub const CLASSID_FMA: u32 = 0x0000_0901;
62+
/// Anatomy is **public reference, not Health PHI** — moved off `0x0901` to
63+
/// clear the collision with OGAR `patient`. Resolves to [`ReadMode::FMA`]
64+
/// (cold `Compressed` reference + `CoarseOnly`).
65+
pub const CLASSID_FMA: u32 = 0x0000_0A01;
6166
/// **Project-management** domain root (`0x01`) — OpenProject ↔ Redmine
6267
/// (work items, members, versions, …). OGAR codebook `0x01XX`. Resolves to
6368
/// [`ReadMode::PROJECT`].
@@ -1754,13 +1759,19 @@ mod tests {
17541759
assert_eq!(fma.edge_codec, EdgeCodecFlavor::CoarseOnly);
17551760

17561761
// The classids follow OGAR `0xDDCC` (ISS-CLASSID-OGAR-DRIFT realign):
1757-
// OSINT domain root `0x0700` (`>>8 == 0x07`); FMA = anatomy concept
1758-
// `0x0901` in the Health domain (`>>8 == 0x09`). Never the pre-realign
1759-
// 0x0007 (OGAR Reserved) / 0x0008 (OGAR OCR) values.
1762+
// OSINT domain root `0x0700` (`>>8 == 0x07`); FMA = `anatomical_structure`
1763+
// `0x0A01` in the **Anatomy** domain (`>>8 == 0x0A`) — re-realigned off
1764+
// `0x0901` to clear the OGAR `patient` collision. Never the pre-realign
1765+
// 0x0007 / 0x0008, nor the colliding 0x0901.
17601766
assert_eq!(NodeGuid::CLASSID_OSINT, 0x0000_0700);
1761-
assert_eq!(NodeGuid::CLASSID_FMA, 0x0000_0901);
1767+
assert_eq!(NodeGuid::CLASSID_FMA, 0x0000_0A01);
1768+
assert_ne!(
1769+
NodeGuid::CLASSID_FMA,
1770+
0x0000_0901,
1771+
"must not alias `patient`"
1772+
);
17621773
assert_eq!(NodeGuid::CLASSID_OSINT >> 8, 0x07, "OSINT domain high byte");
1763-
assert_eq!(NodeGuid::CLASSID_FMA >> 8, 0x09, "Health domain high byte");
1774+
assert_eq!(NodeGuid::CLASSID_FMA >> 8, 0x0A, "Anatomy domain high byte");
17641775
assert_eq!(
17651776
NodeGuid::new(NodeGuid::CLASSID_OSINT, 1, 2, 3, 0xAB, 0xCD).read_mode(),
17661777
ReadMode::OSINT

crates/lance-graph-contract/src/ogar_codebook.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,15 @@ pub enum ConceptDomain {
5252
Osint,
5353
/// `0x08XX` — OCR (optical character recognition / document extraction).
5454
Ocr,
55-
/// `0x09XX` — Health (clinical / patient / care; FMA anatomy lives here).
55+
/// `0x09XX` — Health (clinical / patient / care).
5656
Health,
57+
/// `0x0AXX` — Anatomy (FMA reference ontology; bones / skeleton / joints).
58+
/// Public structural reference, distinct from `Health` PHI — the FMA
59+
/// anatomy domain (`anatomical_structure` / `skeleton` / `bone` / `joint`).
60+
Anatomy,
5761
/// `0x0BXX` — Auth (identity / authz: AuthStore, Zitadel, Zanzibar, Ory Keto).
5862
Auth,
59-
/// Any high-byte slot not yet assigned a domain (`0x03XX`–`0x06XX`, `0x0AXX`, `0x0CXX`+).
63+
/// Any high-byte slot not yet assigned a domain (`0x03XX`–`0x06XX`, `0x0CXX`+).
6064
Unassigned,
6165
}
6266

@@ -73,6 +77,7 @@ pub fn canonical_concept_domain(id: u16) -> ConceptDomain {
7377
0x07 => ConceptDomain::Osint,
7478
0x08 => ConceptDomain::Ocr,
7579
0x09 => ConceptDomain::Health,
80+
0x0A => ConceptDomain::Anatomy,
7681
0x0B => ConceptDomain::Auth,
7782
_ => ConceptDomain::Unassigned,
7883
}
@@ -302,6 +307,15 @@ pub const CODEBOOK: &[(&str, u16)] = &[
302307
("treatment", 0x0905),
303308
("visit", 0x0906),
304309
("vital_sign", 0x0907),
310+
// ── 0x0AXX — Anatomy domain (FMA reference ontology; public, not PHI) ──
311+
// FMA anatomy lives HERE, not in Health 0x09 — reference structure is
312+
// public, a clinical finding *about* it is PHI. `CLASSID_FMA` retargets to
313+
// `anatomical_structure` (0x0A01), clearing the prior 0x0901 = `patient`
314+
// collision. Mirrors OGAR `ogar-vocab` ConceptDomain::Anatomy.
315+
("anatomical_structure", 0x0A01),
316+
("skeleton", 0x0A02),
317+
("bone", 0x0A03),
318+
("joint", 0x0A04),
305319
// ── 0x0BXX — Auth domain (identity / authz; OGAR's 0x0B AuthStore family) ──
306320
("auth_store", 0x0B01),
307321
("auth_zitadel", 0x0B02),
@@ -378,6 +392,7 @@ mod tests {
378392
assert_eq!(canonical_concept_domain(0x0700), ConceptDomain::Osint);
379393
assert_eq!(canonical_concept_domain(0x0801), ConceptDomain::Ocr);
380394
assert_eq!(canonical_concept_domain(0x0901), ConceptDomain::Health);
395+
assert_eq!(canonical_concept_domain(0x0A01), ConceptDomain::Anatomy);
381396
assert_eq!(canonical_concept_domain(0x0B01), ConceptDomain::Auth);
382397
assert_eq!(canonical_concept_domain(0x0500), ConceptDomain::Unassigned);
383398
}
@@ -400,8 +415,9 @@ mod tests {
400415
);
401416
assert_eq!(
402417
classid_concept_domain(NodeGuid::CLASSID_FMA),
403-
ConceptDomain::Health,
404-
"FMA anatomy lives in the Health domain (0x09XX)"
418+
ConceptDomain::Anatomy,
419+
"FMA anatomy lives in the Anatomy domain (0x0AXX), not Health — \
420+
cleared the 0x0901 = `patient` collision"
405421
);
406422
assert_eq!(
407423
classid_concept_domain(NodeGuid::CLASSID_DEFAULT),

0 commit comments

Comments
 (0)