Skip to content

feat(ogar-obo): OBO-core reference bake → 512-byte SoA + EL saturation - #230

Merged
AdaWorldAPI merged 3 commits into
mainfrom
claude/ogar-obo-core-bake
Aug 1, 2026
Merged

feat(ogar-obo): OBO-core reference bake → 512-byte SoA + EL saturation#230
AdaWorldAPI merged 3 commits into
mainfrom
claude/ogar-obo-core-bake

Conversation

@AdaWorldAPI

Copy link
Copy Markdown
Owner

New public reference crate ogar-obo (sibling of ogar-fma / ogar-cpic) + the 0x03 Ontology domain reservation in ogar-vocab.

What it is

Parses the OBO Foundry biomedical core — MONDO (disease) · HPO (phenotype) · Uberon (anatomy) · PATO (quality) · RO (relations) — into the canon 512-byte SoA NodeRow geometry (key(16)|edges(16)|value(480) LE) the lance-graph loader reads zero-copy, plus the OWL-EL completion subset the OBO EL profile actually exercises.

Loader connection = byte-layout contract (not a code dep)

ogar-obo emits the exact lance_graph_contract::canonical_node::NodeRow bytes; node_rows_from_le_bytes reads them back as &[NodeRow] with no deserialize. Proven by the round-trip test (as_le_bytesrows_from_le_bytes, 512×N, 64-align gate, byte-identical, refuses misaligned). Crate stays lean (deps: ogar-vocab only).

Classids — plug-and-play 0x03 Ontology domain

Reserved in ogar-vocab as ConceptDomain::Ontology with zero shared CODEBOOK rows (same posture as OSINT 0x07 / Genetics 0x0E). The concept ids live in ogar-obo (mondo 0x0301 · hpo 0x0302 · uberon 0x0303 · pato 0x0304 · ro 0x0305), so only consumers that dep ogar-obo compile them — ERP / project consumers never pull the OBO concepts into their concept space. Public reference, firewall-separated from 0x09 Health PHI. Fixes two collisions the first cut would have hit (0x0B = Auth, 0x0A02 = skeleton).

Preserved, never truncated

is_a/part_of rails · has_phenotype/has_location convergence · HP anatomy:quality grounding from hp-base.owl logical defs · all external xrefs (MeSH · UMLS · OMIM · Orphanet · SNOMED · ICD) — the projection-join / multilateration bearings and the MeSH clinical-guideline lookup path.

EL saturation (reason.rs)

ELK subset excavated to plain Rust — is_a transitivity, transitive-role part_of, and the R∃ existential-through-spine propagation (grounding inherited up). Iterative Tarjan cycle check + Kahn topo-DP closures.

Full bake on the pinned sources

68,797 rows (35 MB) · 0 cycles · 0 dangling · backbone MONDO→HP/Uberon + HP→Uberon/PATO resolving · 212k xrefs (9.2k MeSH) · EL 738k is_a / 1.6M part_of / 9.4M existential-inferred.

Sources pinned in manifest.json (PURL · version · sha256 · SPDX); the derived .soa + frozen CC-BY sources ship as the ogar-obo-v0.1.0 release. Pure public reference; zero PHI.

ogar-obo 8 tests · ogar-vocab 141 tests · clippy-clean.


Generated by Claude Code

claude added 3 commits August 1, 2026 10:33
New public reference crate (sibling of ogar-fma/ogar-cpic). Parses the OBO
Foundry core — MONDO (disease) · HPO (phenotype) · Uberon (anatomy) · PATO
(quality) · RO (relations) — into the canon 512-byte NodeRow geometry
(key|edges|value LE) the lance-graph loader reads zero-copy via
node_rows_from_le_bytes. Byte compatibility proven by the round-trip test
(as_le_bytes ↔ rows_from_le_bytes, 512×N, 64-align gate); no cross-repo
compile coupling. Classids canon-high (concept<<16 | app): Uberon rides the
0x0A Anatomy domain, disease/phenotype/quality/relations the 0x0B
OBO-clinical-reference domain.

Preserved, never truncated: is_a/part_of rails, has_phenotype/location
convergence, HP anatomy:quality grounding from hp-base.owl logical defs, and
all external xrefs (MeSH · UMLS · OMIM · Orphanet · SNOMED · ICD) — the
projection-join / multilateration bearings and the MeSH guideline-spider path.

reason.rs: the OWL-EL completion subset the OBO EL profile exercises, excavated
to plain Rust — is_a transitivity, transitive-role part_of, and R∃
existential-through-spine (grounding inherited up). Iterative Tarjan cycle
check + Kahn topo-DP closures.

Full bake on the pinned sources: 68,797 rows (35 MB), 0 cycles, 0 dangling,
backbone MONDO→HP/Uberon + HP→Uberon/PATO all resolving, 212k xrefs (9.2k
MeSH). Sources pinned in manifest.json (PURL·version·sha256·SPDX); the .soa
artifact is a gitignored release asset. Pure public CC-BY; zero PHI.

8 tests, clippy-clean.
…ows)

Registers the OBO reference domain in the canonical codebook as a RESERVED,
zero-vocabulary-row block — the same posture as 0x07 OSINT and 0x0E Genetics.
ConceptDomain::Ontology + the 0x03 → Ontology routing arm give consumers a
stable domain tag from `id >> 8`, while the concept ids themselves live in the
producer crate ogar-obo (Namespace::concept_id). This keeps the OBO reference
PLUG-AND-PLAY: only a consumer that deps ogar-obo compiles the concepts; ERP /
project consumers (odoo-rs, openproject-nexgen-rs, …) never pull them into
their concept space. Public reference, firewall-separated from 0x09 Health PHI
(reference ≠ PHI, same split as Anatomy 0x0A).

Fixes two classid collisions in ogar-obo's first cut: 0x0B was already Auth
(auth_store…) and 0x0A02 was `skeleton`. All five OBO namespaces now sit in the
collision-free 0x03 domain: mondo 0x0301 · hpo 0x0302 · uberon 0x0303 · pato
0x0304 · ro 0x0305. Uberon cross-references FMA (ogar-fma, 0x0A Anatomy) by
edge, not by shared domain byte. Bake re-verified (68,797 rows, loader contract
green, 212k xrefs / 9.2k MeSH preserved); manifest artifact sha refreshed.

ogar-vocab 141 tests, ogar-obo 8 tests, clippy-clean.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e9a2e45c94

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +343 to +347
(Mondo, Hpo) => Predicate::HasPhenotype,
(Mondo, Uberon) => Predicate::HasLocation,
(Hpo, Uberon) => Predicate::HasAnatomy,
(Hpo, Pato) => Predicate::HasQuality,
(Uberon, Uberon) => Predicate::PartOf,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Classify relationships from their predicate CURIE

For any intra-Uberon relationship whose predicate is not part_of, this namespace-only mapping still emits Predicate::PartOf; the parser has the actual relation CURIE in the first token of relationship: but discards it. reason::saturate then treats the mislabeled edge as transitive and adds it to the anatomy spine, producing false part_of and existential closure results for the pinned Uberon bake. Parse known predicate CURIEs such as BFO:0000050 directly and preserve unsupported relations as Other.

Useful? React with 👍 / 👎.

Comment on lines +77 to +79
// Write the artifact + verify it round-trips through the loader contract.
let bytes = as_le_bytes(&baked.rows);
std::fs::write(&out, bytes).unwrap_or_else(|e| panic!("write {out}: {e}"));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Serialize triples and xrefs with the release artifact

In the advertised bake_obo release path, the only persisted data is baked.rows; baked.triples, baked.xrefs, and all inferred closure data are merely counted and then discarded. Because each row contains only a degree histogram and namespace, the resulting obo-core.soa has neither edge destinations nor xref IDs, so a consumer loading the release asset cannot perform the documented graph traversal, MeSH lookup, or use the claimed EL saturation. Persist these tables in the artifact or deterministic sidecars and include them in the release contract.

Useful? React with 👍 / 👎.

Comment on lines +313 to +314
for (i, d) in deg.iter().enumerate() {
row.0[EDGES_OFFSET + i] = (*d).min(255) as u8;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep degree counts out of EdgeBlock slots

Whenever a node has any parsed edge, these bytes populate the canonical EdgeBlock's 12 in-family/4 out-of-family adjacency slots with degree counts rather than edge references. A lance-graph consumer accepts the row as a NodeRow and interprets values such as 1 or 2 as adjacency entries, yielding bogus neighbors rather than a histogram. The block must remain zero until valid adjacency is encoded, or the histogram needs a registered value-tenant/sidecar representation.

Useful? React with 👍 / 👎.

Comment on lines +290 to +293
let id = identity.to_le_bytes(); // low 3 bytes are the 24-bit identity
k[13] = id[0];
k[14] = id[1];
k[15] = id[2];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Encode new ontology rows with the V3 facet key

Every newly baked OBO row is born with the retired V1 family:u24 | identity:u24 tail, despite the repository canon in CLAUDE.md:9-20 forbidding that shape for new units in favor of the V3 content-blind 4+12 facet. A V3 reader resolves the 12 payload bytes through the class's facet interpretation, so placing the CURIE identity at bytes 13–15 without a registered legacy-outlier interpretation does not provide the promised V3 address and can be decoded as facet-axis data. Mint an approved V3 payload, or explicitly register and encode a sanctioned compatibility variant.

Useful? React with 👍 / 👎.

@AdaWorldAPI
AdaWorldAPI merged commit 21a7d29 into main Aug 1, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants