Skip to content

Commit f757cd7

Browse files
authored
Merge pull request #71 from AdaWorldAPI/claude/v3-substrate-migration-review-o0yoxv
osint/fma/cpic: classid canon:custom half-order flip — q2 consumer sites to canon-HIGH
2 parents 9c1a9e1 + d3d83f6 commit f757cd7

18 files changed

Lines changed: 182 additions & 93 deletions

File tree

cockpit/src/BodyV3.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@ import * as THREE from 'three';
2121
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
2222

2323
const PAGE_BG = 0x0a0e17;
24-
const FMA_V3_CLASSID = 0x10000a01;
24+
// Post-flip form (canon 0x0A01 HIGH, V3 marker 0x1000 LOW — 2026-07-02).
25+
const FMA_V3_CLASSID = 0x0a011000;
26+
// Pre-flip stored form — the body.soa GitHub-Release asset
27+
// (fma-body-soa-v3-v1) still carries it until re-baked + re-released.
28+
const FMA_V3_CLASSID_LEGACY = 0x10000a01;
2529

2630
const LAYERS: { id: number; name: string; color: string }[] = [
2731
{ id: 1, name: 'skin', color: '#dba88a' },
@@ -433,7 +437,7 @@ export function BodyV3() {
433437
{d && (
434438
<div style={{ opacity: 0.6, marginTop: 2 }}>
435439
{d.nConcepts.toLocaleString()} concepts ·{' '}
436-
{d.classid === FMA_V3_CLASSID
440+
{(d.classid === FMA_V3_CLASSID || d.classid === FMA_V3_CLASSID_LEGACY)
437441
? <span style={{ color: '#7fdca0' }}>classid 0x{d.classid.toString(16)} ✓ V3 (part_of:is_a)</span>
438442
: <span style={{ color: '#ff8095' }}>classid 0x{d.classid.toString(16)}</span>}
439443
</div>

cpic/docs/INGEST.md

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,32 @@ Both hierarchies are *already in the CPIC columns* — nothing is invented:
4040
partonomy is the `part_of` axis, and ATC drug codes are a second ready-made `is_a`
4141
cascade.
4242

43-
## classid — pharmacogenomics domain `0x0C`
44-
45-
`classid` prefix-routes the entity kind (the OGAR `ClassView` dispatch). We use domain
46-
`0x0C` (anatomy was `0x0A`):
43+
## classid — pharmacogenomics, Genetics domain `0x0E01` (re-minted 2026-07-02)
44+
45+
> **Note (2026-07-02):** `SAMPLE_GUIDS.tsv` was regenerated from a fresh
46+
> `cargo run --release --bin ingest -- data out 4000` run against this
47+
> re-mint — every row's tail (HEEL/HIP/TWIG/family/identity) is byte-identical
48+
> to the pre-flip sample; only the classid prefix changed.
49+
50+
`classid` prefix-routes the entity kind (the OGAR `ClassView` dispatch). The
51+
original local scheme used domain `0x0C`, which collides with the Automation
52+
domain (`lance-graph-contract::ogar_codebook::ConceptDomain::Automation`) and
53+
predates the operator's Genetics ruling. Re-minted as INTERIM canon-high
54+
Genetics:q2 ids, matching the `lance-graph-contract` classid half-order flip
55+
(canon HIGH / custom LOW): canon `0x0E01` = Genetics domain (`0x0E`) + appid
56+
`0x01` (q2); the LOW half is this crate's local kind slot. This crate is
57+
dep-free and does not pull the real `lance-graph-contract` ClassView
58+
catalogue — the full contract-pull re-mint that dissolves this local scheme
59+
entirely is the tracked follow-up.
4760

4861
| classid | entity | part_of (high) | is_a (low) |
4962
|---|---|---|---|
50-
| `0x000C0001` | gene | `pharmacogenome / CYP / CYP2 / CYP2C / CYP2C19` | `entity / gene` |
51-
| `0x000C0002` | allele (`*2`) | gene partonomy ++ allele | `allele / no_function` |
52-
| `0x000C0003` | diplotype (`*2/*2`) | gene ++ `diplotypes` ++ dip | `diplotype / homozygous` |
53-
| `0x000C0004` | phenotype | gene ++ `phenotypes` ++ result | `phenotype / poor_metabolizer` |
54-
| `0x000C0005` | drug | `pharmacogenome / drugs / name` | `drug / N / N06 / N06A / N06AA` |
55-
| `0x000C0006` | recommendation | `recommendations / g{id} / drug` | `recommendation / strong` |
63+
| `0x0E010001` | gene | `pharmacogenome / CYP / CYP2 / CYP2C / CYP2C19` | `entity / gene` |
64+
| `0x0E010002` | allele (`*2`) | gene partonomy ++ allele | `allele / no_function` |
65+
| `0x0E010003` | diplotype (`*2/*2`) | gene ++ `diplotypes` ++ dip | `diplotype / homozygous` |
66+
| `0x0E010004` | phenotype | gene ++ `phenotypes` ++ result | `phenotype / poor_metabolizer` |
67+
| `0x0E010005` | drug | `pharmacogenome / drugs / name` | `drug / N / N06 / N06A / N06AA` |
68+
| `0x0E010006` | recommendation | `recommendations / g{id} / drug` | `recommendation / strong` |
5669

5770
- **family (u24)** = the basin: the gene symbol (gene/allele/diplotype/phenotype), the
5871
ATC root letter (drug), or `rec:g{id}` (recommendation). Groups all of a gene's
@@ -66,10 +79,10 @@ cascade.
6679

6780
```text
6881
allele guid HEEL HIP TWIG family
69-
CYP2C19 *2 000c0002-c358-ec6f-f76f-d69bfe558274 c358 ec6f f76f d69bfe (No function)
70-
CYP2C9 *2 000c0002-c358-ecd8-f7d8-fbd6cbd5c622 c358 ecd8 f7d8 fbd6cb (Decreased function)
71-
CYP2C19 *1 000c0002-c358-ec07-f707-d69bfe3c1176 c358 ec07 f707 d69bfe (Normal function)
72-
CYP2D6 *4 000c0002-c358-ec6f-f76f-1066f96f7ace c358 ec6f f76f 1066f9 (No function)
82+
CYP2C19 *2 0e010002-c358-ec6f-f76f-d69bfe558274 c358 ec6f f76f d69bfe (No function)
83+
CYP2C9 *2 0e010002-c358-ecd8-f7d8-fbd6cbd5c622 c358 ecd8 f7d8 fbd6cb (Decreased function)
84+
CYP2C19 *1 0e010002-c358-ec07-f707-d69bfe3c1176 c358 ec07 f707 d69bfe (Normal function)
85+
CYP2D6 *4 0e010002-c358-ec6f-f76f-1066f96f7ace c358 ec6f f76f 1066f9 (No function)
7386
```
7487

7588
- **part_of HIGH bytes** `c3 / ec / f7` = `pharmacogenome → CYP → CYP2`, shared by all

cpic/docs/SAMPLE_GUIDS.tsv

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
11
guid kind label part_of is_a
2-
000c0001-c3fa-ec2a-f72a-fbd6cb3779b9 gene CYP2C9 pharmacogenome / CYP / CYP2 / CYP2C / CYP2C9 entity / gene
3-
000c0001-c3fa-ec2a-f72a-1066f93779b9 gene CYP2D6 pharmacogenome / CYP / CYP2 / CYP2D / CYP2D6 entity / gene
4-
000c0001-c3fa-1b2a-982a-61ef4f3779b9 gene HLA-B pharmacogenome / HLA / HLA-B entity / gene
5-
000c0001-c3fa-ec2a-f72a-d69bfe3779b9 gene CYP2C19 pharmacogenome / CYP / CYP2 / CYP2C / CYP2C19 entity / gene
6-
000c0001-c3fa-f92a-8f2a-ec80083779b9 gene TPMT pharmacogenome / TPMT / TPMT entity / gene
7-
000c0002-c358-ec6f-f76f-d69bfe4cda56 allele CYP2C19 *4 pharmacogenome / CYP / CYP2 / CYP2C / CYP2C19 / 4 allele / no_function
8-
000c0002-c358-ec6f-f76f-1066f96f7ace allele CYP2D6 *4 pharmacogenome / CYP / CYP2 / CYP2D / CYP2D6 / 4 allele / no_function
9-
000c0002-c358-1bd5-98d5-61ef4f6ef372 allele HLA-B *57:01 pharmacogenome / HLA / HLA-B / 57_01 allele / uncertain_function
10-
000c0002-c358-ec6f-f76f-d69bfe558274 allele CYP2C19 *2 pharmacogenome / CYP / CYP2 / CYP2C / CYP2C19 / 2 allele / no_function
11-
000c0002-c358-ecd8-f7d8-fbd6cbd5c622 allele CYP2C9 *2 pharmacogenome / CYP / CYP2 / CYP2C / CYP2C9 / 2 allele / decreased_function
12-
000c0002-c358-ec07-f707-d69bfe3c1176 allele CYP2C19 *1 pharmacogenome / CYP / CYP2 / CYP2C / CYP2C19 / 1 allele / normal_function
13-
000c0002-c358-ec6f-f76f-fbd6cb6b6a6d allele CYP2C9 *3 pharmacogenome / CYP / CYP2 / CYP2C / CYP2C9 / 3 allele / no_function
14-
000c0002-c358-ec07-f707-1066f9fd85b3 allele CYP2D6 *1 pharmacogenome / CYP / CYP2 / CYP2D / CYP2D6 / 1 allele / normal_function
15-
000c0004-c347-ecb1-f7b1-1066f93779b9 phenotype CYP2D6 Ultrarapid Metabolizer pharmacogenome / CYP / CYP2 / CYP2D / CYP2D6 / phenotypes / ultrarapid_metabolizer phenotype / ultrarapid_metabolizer
16-
000c0004-c347-ecb1-f7b1-1066f96ef372 phenotype CYP2D6 Ultrarapid Metabolizer pharmacogenome / CYP / CYP2 / CYP2D / CYP2D6 / phenotypes / ultrarapid_metabolizer phenotype / ultrarapid_metabolizer
17-
000c0004-c347-ec7a-f77a-1066f9a66d2b phenotype CYP2D6 Normal Metabolizer pharmacogenome / CYP / CYP2 / CYP2D / CYP2D6 / phenotypes / normal_metabolizer phenotype / normal_metabolizer
18-
000c0004-c347-f9a8-8fa8-ec80083779b9 phenotype TPMT Intermediate Metabolizer pharmacogenome / TPMT / TPMT / phenotypes / intermediate_metabolizer phenotype / intermediate_metabolizer
19-
000c0004-c347-f9e9-8fe9-ec80086ef372 phenotype TPMT Poor Metabolizer pharmacogenome / TPMT / TPMT / phenotypes / poor_metabolizer phenotype / poor_metabolizer
20-
000c0004-c347-f9db-8fdb-ec8008a66d2b phenotype TPMT Indeterminate pharmacogenome / TPMT / TPMT / phenotypes / indeterminate phenotype / indeterminate
21-
000c0005-c3af-cb3e-233c-1c839f6ef372 drug abacavir pharmacogenome / drugs / abacavir drug / J / J05 / J05A / J05AF / abacavir
22-
000c0005-c3af-cb0a-630d-1c7cd36ef372 drug amitriptyline pharmacogenome / drugs / amitriptyline drug / N / N06 / N06A / N06AA / amitriptyline
23-
000c0005-c3af-cba6-3010-1c9137a66d2b drug warfarin pharmacogenome / drugs / warfarin drug / B / B01 / B01A / B01AA / warfarin
24-
000c0005-c3af-cba6-b610-1c9137bbcdc8 drug clopidogrel pharmacogenome / drugs / clopidogrel drug / B / B01 / B01A / B01AC / clopidogrel
25-
000c0006-c7ee-454c-db4c-a2917a3779b9 recommendation g100421 RxNorm:190521 [HLA-B:*57:01 negative] -> Strong recommendations / g100421 / rxnorm_190521 recommendation / strong
26-
000c0006-c7ee-454c-db4c-a2917a6ef372 recommendation g100421 RxNorm:190521 [HLA-B:*57:01 positive] -> Strong recommendations / g100421 / rxnorm_190521 recommendation / strong
2+
0e010001-c3fa-ec2a-f72a-fbd6cb3779b9 gene CYP2C9 pharmacogenome / CYP / CYP2 / CYP2C / CYP2C9 entity / gene
3+
0e010001-c3fa-ec2a-f72a-1066f93779b9 gene CYP2D6 pharmacogenome / CYP / CYP2 / CYP2D / CYP2D6 entity / gene
4+
0e010001-c3fa-1b2a-982a-61ef4f3779b9 gene HLA-B pharmacogenome / HLA / HLA-B entity / gene
5+
0e010001-c3fa-ec2a-f72a-d69bfe3779b9 gene CYP2C19 pharmacogenome / CYP / CYP2 / CYP2C / CYP2C19 entity / gene
6+
0e010001-c3fa-f92a-8f2a-ec80083779b9 gene TPMT pharmacogenome / TPMT / TPMT entity / gene
7+
0e010002-c358-ec6f-f76f-d69bfe4cda56 allele CYP2C19 *4 pharmacogenome / CYP / CYP2 / CYP2C / CYP2C19 / 4 allele / no_function
8+
0e010002-c358-ec6f-f76f-1066f96f7ace allele CYP2D6 *4 pharmacogenome / CYP / CYP2 / CYP2D / CYP2D6 / 4 allele / no_function
9+
0e010002-c358-1bd5-98d5-61ef4f6ef372 allele HLA-B *57:01 pharmacogenome / HLA / HLA-B / 57_01 allele / uncertain_function
10+
0e010002-c358-ec6f-f76f-d69bfe558274 allele CYP2C19 *2 pharmacogenome / CYP / CYP2 / CYP2C / CYP2C19 / 2 allele / no_function
11+
0e010002-c358-ecd8-f7d8-fbd6cbd5c622 allele CYP2C9 *2 pharmacogenome / CYP / CYP2 / CYP2C / CYP2C9 / 2 allele / decreased_function
12+
0e010002-c358-ec07-f707-d69bfe3c1176 allele CYP2C19 *1 pharmacogenome / CYP / CYP2 / CYP2C / CYP2C19 / 1 allele / normal_function
13+
0e010002-c358-ec6f-f76f-fbd6cb6b6a6d allele CYP2C9 *3 pharmacogenome / CYP / CYP2 / CYP2C / CYP2C9 / 3 allele / no_function
14+
0e010002-c358-ec07-f707-1066f9fd85b3 allele CYP2D6 *1 pharmacogenome / CYP / CYP2 / CYP2D / CYP2D6 / 1 allele / normal_function
15+
0e010004-c347-ecb1-f7b1-1066f93779b9 phenotype CYP2D6 Ultrarapid Metabolizer pharmacogenome / CYP / CYP2 / CYP2D / CYP2D6 / phenotypes / ultrarapid_metabolizer phenotype / ultrarapid_metabolizer
16+
0e010004-c347-ecb1-f7b1-1066f96ef372 phenotype CYP2D6 Ultrarapid Metabolizer pharmacogenome / CYP / CYP2 / CYP2D / CYP2D6 / phenotypes / ultrarapid_metabolizer phenotype / ultrarapid_metabolizer
17+
0e010004-c347-ec7a-f77a-1066f9a66d2b phenotype CYP2D6 Normal Metabolizer pharmacogenome / CYP / CYP2 / CYP2D / CYP2D6 / phenotypes / normal_metabolizer phenotype / normal_metabolizer
18+
0e010004-c347-f9a8-8fa8-ec80083779b9 phenotype TPMT Intermediate Metabolizer pharmacogenome / TPMT / TPMT / phenotypes / intermediate_metabolizer phenotype / intermediate_metabolizer
19+
0e010004-c347-f9e9-8fe9-ec80086ef372 phenotype TPMT Poor Metabolizer pharmacogenome / TPMT / TPMT / phenotypes / poor_metabolizer phenotype / poor_metabolizer
20+
0e010004-c347-f9db-8fdb-ec8008a66d2b phenotype TPMT Indeterminate pharmacogenome / TPMT / TPMT / phenotypes / indeterminate phenotype / indeterminate
21+
0e010005-c3af-cb3e-233c-1c839f6ef372 drug abacavir pharmacogenome / drugs / abacavir drug / J / J05 / J05A / J05AF / abacavir
22+
0e010005-c3af-cb0a-630d-1c7cd36ef372 drug amitriptyline pharmacogenome / drugs / amitriptyline drug / N / N06 / N06A / N06AA / amitriptyline
23+
0e010005-c3af-cba6-3010-1c9137a66d2b drug warfarin pharmacogenome / drugs / warfarin drug / B / B01 / B01A / B01AA / warfarin
24+
0e010005-c3af-cba6-b610-1c9137bbcdc8 drug clopidogrel pharmacogenome / drugs / clopidogrel drug / B / B01 / B01A / B01AC / clopidogrel
25+
0e010006-c7ee-454c-db4c-a2917a3779b9 recommendation g100421 RxNorm:190521 [HLA-B:*57:01 negative] -> Strong recommendations / g100421 / rxnorm_190521 recommendation / strong
26+
0e010006-c7ee-454c-db4c-a2917a6ef372 recommendation g100421 RxNorm:190521 [HLA-B:*57:01 positive] -> Strong recommendations / g100421 / rxnorm_190521 recommendation / strong

cpic/src/lib.rs

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,23 @@
66
//!
77
//! POC over published CPIC rules — NOT clinical decision support.
88
9-
// ── classid: pharmacogenomics domain 0x0C (cf. anatomy 0x0A used by fma/converge) ──
10-
pub const CID_GENE: u32 = 0x000C_0001;
11-
pub const CID_ALLELE: u32 = 0x000C_0002;
12-
pub const CID_DIPLOTYPE: u32 = 0x000C_0003;
13-
pub const CID_PHENOTYPE: u32 = 0x000C_0004;
14-
pub const CID_DRUG: u32 = 0x000C_0005;
15-
pub const CID_REC: u32 = 0x000C_0006;
9+
// ── classid: pharmacogenomics — re-minted 2026-07-02. The original local scheme
10+
// (`0x000C_000N`) predated the operator's Genetics ruling and collided with the
11+
// Automation domain (0x0C is Automation, not Genetics — see
12+
// `lance-graph-contract::ogar_codebook::ConceptDomain::Automation`). Re-minted as
13+
// INTERIM canon-high Genetics:q2 ids, matching the `lance-graph-contract` classid
14+
// half-order flip (canon in the HIGH half, custom in the LOW half): canon `0x0E01`
15+
// = Genetics domain (`0x0E`) + appid `0x01` (q2); the LOW half is this crate's
16+
// local kind slot (GENE=1, ALLELE=2, DIPLOTYPE=3, PHENOTYPE=4, DRUG=5, REC=6).
17+
// This is dep-free and does NOT pull the real `lance-graph-contract` ClassView
18+
// catalogue — the full contract-pull re-mint that dissolves this local scheme
19+
// entirely is the tracked follow-up (see `docs/INGEST.md`).
20+
pub const CID_GENE: u32 = 0x0E01_0001;
21+
pub const CID_ALLELE: u32 = 0x0E01_0002;
22+
pub const CID_DIPLOTYPE: u32 = 0x0E01_0003;
23+
pub const CID_PHENOTYPE: u32 = 0x0E01_0004;
24+
pub const CID_DRUG: u32 = 0x0E01_0005;
25+
pub const CID_REC: u32 = 0x0E01_0006;
1626

1727
// ── FNV-1a (the same prefix-cascade generator the fma converge bin uses) ──
1828
const FNV_OFFSET: u64 = 0xcbf2_9ce4_8422_2325;

crates/aiwar-ingest/tests/fixtures/codebook_normalize.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
into ONE codebook-based, non-serialized Gotham/neo4j test fixture.
44
55
CANON model (lance-graph contract::aiwar + E-FAMILY-ADAPTER + OGAR codebook):
6-
- classid OSINT = 0x0700 (NodeGuid::CLASSID_OSINT, >>8 == 0x07)
6+
- classid OSINT = 0x0700 (NodeGuid::CLASSID_OSINT, >>8 == 0x07) — this is the
7+
bare u16 canon id, the HIGH half of the composed u32 classid since the
8+
2026-07-02 half-order flip (NodeGuid::CLASSID_OSINT == 0x0700_0000); this
9+
fixture never composes the full u32, so no functional change from the flip.
710
- a node is its HEAD only: classid | family(mixin) | identity(u16) | edge-adapters
811
- mixin: an entity inherits its category by REFERENCE (family-node id), never a copy
912
- identity = 4 nibbles (u16)
@@ -13,6 +16,9 @@
1316
import json, re, sys, glob, os
1417

1518
ROOT = os.environ.get("AIWAR_HARVEST", "/home/user/aiwar-neo4j-harvest")
19+
# u16 canon id — the HIGH half of the composed u32 classid since the
20+
# 2026-07-02 flip (NodeGuid::CLASSID_OSINT == 0x0700_0000). This script only
21+
# ever emits the bare u16 (see @meta below), never the composed u32.
1622
OSINT_CLASSID = 0x0700
1723

1824
# JSON N_<group> -> canonical family label (matches the cypher node labels)

crates/cockpit-server/src/main.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,8 @@ async fn main() {
217217
// CPIC pharmacogenomics for the /cpic cockpit (cpic::reason over the baked CPIC tables)
218218
.route("/api/cpic/reason", post(pgx::cpic_reason_handler))
219219
.route("/api/cpic/catalog", get(pgx::cpic_catalog_handler))
220-
// OSINT domain (classid 0x0700): the harvest as a CANON family-basin graph
220+
// OSINT domain (canon classid 0x0700 — HIGH half since the 2026-07-02
221+
// flip): the harvest as a CANON family-basin graph
221222
// (round→anchor basins, GUID-v2 tail), displayed via the OGAR ClassView.
222223
.route("/api/graph/osint", get(osint_gotham::osint_graph_handler))
223224
// Pre-baked enriched OSINT SoA bytes — the 3D view (/osint3d) fetches

crates/cockpit-server/src/osint_gotham.rs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
//! OSINT / Palantir-Gotham domain (classid `0x0700`) — the aiwar harvest as a
22
//! CANON family-basin graph, rendered through the OGAR Active-Record `ClassView`.
3+
//! `0x0700` is the canon concept id: since the 2026-07-02 half-order flip it is
4+
//! the HIGH u16 of the composed `u32` classid (`0x0700_0000`, `NodeGuid::CLASSID_OSINT`);
5+
//! the pre-flip stored form `0x0000_0700` still resolves via `CLASSID_OSINT_LEGACY`.
6+
//! Bare `0x0700` below always means the canon value, not the full composed classid.
37
//!
48
//! The corrected model (operator-locked this session):
59
//!
@@ -500,9 +504,12 @@ pub fn osint_graph() -> &'static Arc<RwLock<GraphSnapshot>> {
500504
OSINT_GRAPH.get_or_init(|| Arc::new(RwLock::new(GraphSnapshot::empty())))
501505
}
502506

503-
/// The ClassView ClassId for the OSINT domain (low u16 of `CLASSID_OSINT`).
507+
/// The ClassView ClassId for the OSINT domain — the concept id, i.e. the CANON
508+
/// half of `CLASSID_OSINT` (the HIGH u16 since the 2026-07-02 half-order flip;
509+
/// `classid & 0xFFFF` would now read the CUSTOM half and silently return the
510+
/// wrong value).
504511
fn osint_class_id() -> u16 {
505-
(NodeGuid::CLASSID_OSINT & 0xFFFF) as u16
512+
lance_graph_contract::classid_concept(NodeGuid::CLASSID_OSINT)
506513
}
507514

508515
// ─────────────────────────────────────────────────────────────────────────────
@@ -826,7 +833,13 @@ pub fn build_osint_gotham(graph: &AiWarGraph, rounds: &[EncounterRound]) -> Grap
826833
let class_label = label_of_order(order);
827834
let mut props: HashMap<String, Value> = src.properties.clone();
828835
props.insert("guid".to_string(), Value::String(r.key.to_hex_v2()));
829-
props.insert("classid".to_string(), Value::String("00000700".to_string()));
836+
// Compose dynamically rather than hardcoding the stored form — the
837+
// 2026-07-02 half-order flip moved canon 0x0700 into the HIGH half,
838+
// so this now yields "07000000" (was "00000700" pre-flip).
839+
props.insert(
840+
"classid".to_string(),
841+
Value::String(format!("{:08x}", NodeGuid::CLASSID_OSINT)),
842+
);
830843
props.insert("class_order".to_string(), Value::from(order));
831844
props.insert("class".to_string(), Value::String(class_label.to_string()));
832845
props.insert("basin".to_string(), Value::String(format!("{basin:02x}")));
@@ -1249,9 +1262,14 @@ mod tests {
12491262
let rows = osint_node_rows(&g, &plan);
12501263
assert_eq!(rows.len(), g.node_count(), "one OSINT row per entity");
12511264
for (i, row) in rows.iter().enumerate() {
1252-
// classid 0x0700 (the OSINT domain byte is 0x07)
1265+
// classid 0x0700_0000 (canon 0x0700 sits in the HIGH half since
1266+
// the 2026-07-02 flip; route through the contract helper rather
1267+
// than deriving the domain byte via a raw shift).
12531268
assert_eq!(row.key.classid(), NodeGuid::CLASSID_OSINT);
1254-
assert_eq!(row.key.classid() >> 8, 0x07);
1269+
assert_eq!(
1270+
lance_graph_contract::ogar_codebook::classid_canon(row.key.classid()) >> 8,
1271+
0x07
1272+
);
12551273
// GUID-v2 tail: identity == index, family == basin byte (high byte 0)
12561274
assert_eq!(row.key.identity_v2(), i as u16);
12571275
assert_eq!(row.key.family_v2() >> 8, 0, "basin is an 8-bit byte");

crates/osint-bake/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ path = "src/main.rs"
1515
[dependencies]
1616
aiwar-ingest = { path = "../aiwar-ingest" }
1717
# osint-bake is the ONLY crate that mints on the V3 cascade tail (the FMA bake:
18-
# CLASSID_FMA_V3 0x1000_0A01 → ReadMode::FMA_V3, the part_of:is_a reading of the
18+
# CLASSID_FMA_V3 0x0A01_1000 (canon 0x0A01 HIGH, V3 marker 0x1000 LOW — 2026-07-02
19+
# half-order flip) → ReadMode::FMA_V3, the part_of:is_a reading of the
1920
# SAME leaf·family·identity bytes). guid-v3-tail is requested here, NOT workspace-
2021
# wide, so it doesn't force the feature onto cockpit-server's Railway build.
2122
lance-graph-contract = { workspace = true, features = ["guid-v3-tail"] }

0 commit comments

Comments
 (0)