|
50 | 50 | | ADR-020 | SDK endgame is deeper than Foundry going OSS via three structural differentiators (migration scaffold, self-hosting reference, substrate-layer OSS) | **Pinned** | OGAR PR #20 §5.3 | |
51 | 51 | | ADR-021 | **Meta-hygiene**: always grep peer crates before copying manifest patterns (the `[lints] workspace = true` cascade lesson) | **Pinned** | OGAR PR #15 + PR #17/#18 follow-ups | |
52 | 52 | | ADR-022 | **The Firewall** — absolute inner/outer boundary; no serialization in hot path; inner = compile-time HHTL; outer = contract-trait pluggable | **Pinned** | OGAR (this PR); `docs/THE-FIREWALL.md` | |
| 53 | +| ADR-023 | **IR-as-wire-truth** — the source-language AST is *input dialect*; the canonical `Class`/`Attribute`/`Association`/`EnumDecl`/`ActionDef` IR is *wire truth*. Adapters lift dialects into IR; the IR routes everything (registry key, actor mailbox, Lance version, audit-log dimension) | **Pinned** | OGAR (this PR); `crates/ogar-vocab/`; `bardioc/substrate-b-shadow::EdgeDecoder<E>` (PR #19) | |
53 | 54 |
|
54 | 55 | ## ADR-001: `State = ActionState` (lifecycle), not domain state, for Rubicon binding |
55 | 56 |
|
@@ -1058,6 +1059,114 @@ designed to produce. |
1058 | 1059 | - lance-graph PR #470 (`.claude/handovers/2026-06-05-0445-bardioc-to- |
1059 | 1060 | lance-graph-bindspace-arch-delta.md` — the lance-graph-side pointer). |
1060 | 1061 |
|
| 1062 | +## ADR-023: IR-as-wire-truth — Class is the wire format, not the source AST |
| 1063 | + |
| 1064 | +**Status:** Pinned (2026-06-05). Companion to ADR-022 (The Firewall); |
| 1065 | +captures the framing principle the firewall's inner side has been |
| 1066 | +operating under. |
| 1067 | + |
| 1068 | +**Context.** Cross-session conversation surfaced the question |
| 1069 | +*"what's the wire format between source-language frontends and the |
| 1070 | +substrate?"* — raised in the context of Elixir ASTs, ClickHouse DDL, |
| 1071 | +SurrealQL DDL, FIBO/FMA TTL, and the planned `ch`/`ecto_ch` shadow |
| 1072 | +extraction. The naive answer ("forward the source AST as-is") is |
| 1073 | +wrong; the firewall's inner discipline already implies the right |
| 1074 | +answer, but it hadn't been named explicitly. |
| 1075 | + |
| 1076 | +**Decision.** The canonical wire format is the OGAR IR — `Class`, |
| 1077 | +`Attribute`, `Association`, `EnumDecl`, `ActionDef`, `KausalSpec`, |
| 1078 | +`Identity` (the `NiblePath` prefix-radix). Source-language ASTs |
| 1079 | +(Elixir quoted form, SurrealQL DDL AST, Ruby AR macro tree, Odoo |
| 1080 | +Python `models.Model` shape, ClickHouse CREATE TABLE, OWL TTL |
| 1081 | +triples) are *input dialects* — each lifted into the canonical IR |
| 1082 | +by a dedicated **adapter crate**. Once lifted, everything downstream |
| 1083 | +(registry key, actor mailbox routing, Lance version stamp, |
| 1084 | +audit-log dimension, HHTL compile-time codegen) routes through the |
| 1085 | +*same* IR. |
| 1086 | + |
| 1087 | +The aphorism: **"Elixir AST is input dialect; the canonical IR is |
| 1088 | +wire truth."** Generalizes to any source dialect; the IR is the |
| 1089 | +shared substrate. |
| 1090 | + |
| 1091 | +**Alternatives considered.** |
| 1092 | + |
| 1093 | +- *Forward the source AST as the wire format.* Rejected: leaks |
| 1094 | + source-language syntax + semantics into every downstream consumer; |
| 1095 | + breaks the firewall's "no serialization in hot path" invariant |
| 1096 | + (source ASTs are too rich + heterogeneous to be compile-time- |
| 1097 | + HHTL-resolvable); makes cross-source comparison (e.g. §14 oracle |
| 1098 | + equivalence-running between OLD-stack Elixir + NEW-stack Rust) |
| 1099 | + arbitrarily hard because the comparison surface differs per source. |
| 1100 | +- *Use a "least common denominator" subset of OWL DL.* Rejected: OWL |
| 1101 | + doesn't model state machines or lifecycle behaviour (the |
| 1102 | + `ActionDef` + `KausalSpec` axis OGAR adds past OWL DL); the LCD |
| 1103 | + surface would be insufficient. OGAR sits *above* OWL DL (OWL is |
| 1104 | + one of OGAR's supported source dialects, not a constraint on the |
| 1105 | + IR). |
| 1106 | + |
| 1107 | +**Consequences.** |
| 1108 | + |
| 1109 | +- **Same IR → same hash → same actor routing → same Lance row → |
| 1110 | + same audit dimension.** Content-addressing primitive. Already |
| 1111 | + realized in code: `ogar-ontology::class_identity(prefix, name)` |
| 1112 | + produces the canonical identity string; PR #31 closed the |
| 1113 | + collision hazard; bardioc PR #19 (`substrate-b-shadow::EdgeDecoder<E>`) |
| 1114 | + consumes the IR as `ActionInvocation` at the OLD-stack-shadow seam. |
| 1115 | + |
| 1116 | +- **Adapters are pluggable, the IR is fixed.** New source dialects |
| 1117 | + ship as new adapter crates (`ogar-adapter-surrealql`, |
| 1118 | + `ogar-adapter-ttl` planned, `ogar-from-elixir`, `ogar-from-ecto` |
| 1119 | + proposed). The `Class` IR doesn't change; only the lift code does. |
| 1120 | + |
| 1121 | +- **Round-trip is the adapter contract.** `parse_<dialect>` → |
| 1122 | + `Vec<Class>` → `emit_<dialect>` should reproduce the source. OGAR |
| 1123 | + PR #32 demonstrated this for SurrealQL DDL; round-trip tests |
| 1124 | + are now part of the adapter contract. |
| 1125 | + |
| 1126 | +- **The `schema_ddl_hint` loop closes here.** PR #25 introduced |
| 1127 | + `KnowableFromStore::register(class_identity, schema_ddl_hint: |
| 1128 | + Option<&str>)` with the docstring claim *"so the registry is |
| 1129 | + self-describing"*. PR #32 landed `emit_surrealql_ddl`. This PR |
| 1130 | + wires the two together (feature-gated `surrealql-hint`): the |
| 1131 | + registry now carries the producer's `Class` IR projected into |
| 1132 | + SurrealQL DDL alongside the `knowable_from` stamp. The IR-as-wire- |
| 1133 | + truth claim is no longer aspirational. |
| 1134 | + |
| 1135 | +- **Cross-session triangulation receipt.** bardioc PR #19 |
| 1136 | + (`substrate-b-shadow`) consumes `ogar-vocab` as a direct |
| 1137 | + dependency — its `EdgeDecoder<E>` trait IS the IR-as-wire-truth |
| 1138 | + pattern in code. The HIRO-Graph + ClickHouse decoders return |
| 1139 | + `ActionInvocation` regardless of source; the rest of the substrate |
| 1140 | + consumes one shape. |
| 1141 | + |
| 1142 | +**Change policy.** Adding a new source dialect (new adapter crate) |
| 1143 | +is routine. Changing the IR — adding a field to `Class`, |
| 1144 | +`AssociationKind`, `EnumSource`, `KausalSpec` — is a substrate-wide |
| 1145 | +contract change requiring (a) backward-compatible default (typically |
| 1146 | +`Option<…>` field), (b) round-trip preservation in all adapter |
| 1147 | +crates, (c) consultation with the runtime session (bardioc / |
| 1148 | +lance-graph) before merge. |
| 1149 | + |
| 1150 | +**References.** |
| 1151 | + |
| 1152 | +- `crates/ogar-vocab/` — the canonical IR. |
| 1153 | +- `crates/ogar-ontology/` — identity routing + canonical-form helpers. |
| 1154 | +- `crates/ogar-knowable-from/` — the registry seam; this PR wires |
| 1155 | + the `schema_ddl_hint` loop via the `surrealql-hint` feature. |
| 1156 | +- `crates/ogar-adapter-surrealql/` — first round-trip adapter (PR |
| 1157 | + #24 wired the parser; PR #32 closed the walk + round-trip). |
| 1158 | +- `crates/ogar-from-elixir/` — Elixir SchemaSource scaffold. |
| 1159 | +- ADR-022 (The Firewall) — the invariant ADR-023 makes explicit. |
| 1160 | +- ADR-016 (SurrealQL DDL AST is not the universal IR) — the |
| 1161 | + predecessor; ADR-023 generalizes ADR-016's claim from SurrealQL |
| 1162 | + to *all* source dialects. |
| 1163 | +- bardioc PR #17 (Rubicon Phases 1-5) — consumer of `ogar-vocab` |
| 1164 | + for actor dispatch. |
| 1165 | +- bardioc PR #19 (`substrate-b-shadow::EdgeDecoder<E>`) — the |
| 1166 | + pattern materialized in runtime-side code. |
| 1167 | +- `docs/RDF-OWL-ALIGNMENT.md` §3 (OGAR's position in L1-L5) — the |
| 1168 | + IR sits at the AR-pattern lift seam. |
| 1169 | + |
1061 | 1170 | ## Implementation receipts — ADR ↔ commit cross-reference |
1062 | 1171 |
|
1063 | 1172 | > **Added in follow-up addendum (2026-06-05).** Records the implementation |
|
0 commit comments