Skip to content

Commit a5b901d

Browse files
committed
fix(ogar): PR #564 codex P2 — one contract source + build-time parity fuse
codex P2 #1 (contract source unification): lance-graph + symbiont path-dep lance-graph-contract; lance-graph-ogar git-dep'd it, so when composed Cargo sees two distinct crates and OgarClassView impls the git ClassView, unusable where the engine expects the path one. Fix: path-dep ../lance-graph-contract (the canonical in-repo copy) + a [patch."…/lance-graph"] that folds ogar-class-view's transitive git contract onto the SAME path copy = one source. Documented the cargo limitation: an in-repo workspace root (symbiont) adding this crate MUST repeat the patch ([patch] only applies at the workspace root). codex P2 #2 (parity guard only ran in tests): the drift fuse was #[cfg(test)] only, so a downstream cargo build never ran it — the "fails the build on drift" claim was false for normal builds. Fix: added parity::COUNT_FUSE, a compile-time const assert (mirror::CODEBOOK.len() == ogar_vocab::class_ids::ALL.len()) that fires in ANY build (cargo build included) on add/remove drift; kept the runtime assert_codebook_parity for the full id/domain bijection (tested + callable at startup); corrected the docs to state both depths precisely (no overclaim). Re-verified: cargo test --manifest-path crates/lance-graph-ogar/Cargo.toml 3/3 (the ogar_class_view_implements_contract_class_view test compiling proves one-source unification), clippy -D warnings + fmt clean, no "patch not used". Board: AGENT_LOG (cont.15). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CcpLeEC3XK8Eye53GKBVvi
1 parent 43d2ae4 commit a5b901d

3 files changed

Lines changed: 74 additions & 23 deletions

File tree

.claude/board/AGENT_LOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
## 2026-06-20 (cont.¹⁵) — PR #564 codex P2 fixes (contract-source unification + build-time parity fuse)
2+
3+
**Main thread (Opus), autoattended.** Two codex P2 review comments on #564, both correct, both fixed:
4+
1. **One contract source at the integration boundary** (Cargo.toml): `lance-graph` + `symbiont` path-dep `lance-graph-contract`; `lance-graph-ogar` git-dep'd it → two distinct crates when composed → `OgarClassView` would impl the git `ClassView`, not the path one. Fix: `lance-graph-ogar` now **path-deps** `../lance-graph-contract` (the canonical in-repo copy) + a `[patch."…/lance-graph"] lance-graph-contract = { path = … }` folds ogar-class-view's transitive git contract onto the SAME path copy = ONE source. Documented the cargo limitation: an in-repo workspace root (symbiont) adding this crate MUST repeat the patch (`[patch]` only applies at the root).
5+
2. **Parity guard only ran under `#[cfg(test)]`** (lib.rs) → a downstream `cargo build` never executed it, contradicting the "fails the build on drift" claim. Fix: added a **compile-time length fuse** `parity::COUNT_FUSE` (`const _ = assert!(mirror::CODEBOOK.len() == ogar_vocab::class_ids::ALL.len())`) that fires in ANY build (cargo build included) on add/remove drift; kept the runtime `assert_codebook_parity` (full id/domain bijection, tested + callable at startup); corrected the docs to state both depths precisely (no overclaim).
6+
7+
Re-verified: `cargo test --manifest-path crates/lance-graph-ogar/Cargo.toml` 3/3 (the `ogar_class_view_implements_contract_class_view` test compiling PROVES one-source unification), clippy `-D warnings` + fmt clean, no "patch not used". Both threads replied + resolved. Pushed to #564.
8+
19
## 2026-06-20 (cont.¹⁴) — zero-copy SoA read contract (`node_rows_from_le_bytes`) — the surrealdb "second brain" primitive
210

311
**Main thread (Opus), autoattended.** Operator: "create a contract … that ensures LE contract to the lance-graph SoA view → zero-copy symbiont; surrealdb becomes a second brain inside lance-graph." Brutal feasibility pass against real code on both sides (see EPIPHANY `E-SURREALDB-SECOND-BRAIN-IS-ZERO-COPY-IFF-FIXEDSIZEBINARY`):

crates/lance-graph-ogar/Cargo.toml

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,31 @@
1515
# ogar-adapter-surrealql = emit(Class) -> SurrealQL DDL (the DO arm)
1616
#
1717
# Auto-activation = Cargo presence: a build graph that pulls THIS crate gets the
18-
# real OGAR Class/ClassView/codebook + the parity-guard (lib.rs) that fails the
19-
# build if `lance_graph_contract::ogar_codebook`'s lean mirror ever drifts from
20-
# `ogar_vocab::CODEBOOK`. A build WITHOUT this crate uses the contract's zero-dep
21-
# mirror + the bare ClassView trait (headless OGAR app, or a self-supplied impl).
22-
# OGAR never depends on the lance-graph ENGINE — only on the zero-dep contract.
18+
# real OGAR Class/ClassView/codebook + the parity-guard (lib.rs): a COMPILE-TIME
19+
# length fuse (`const _` assert that the mirror and `ogar_vocab::class_ids::ALL`
20+
# have equal count — fires in ANY build, `cargo build` included) plus a runtime
21+
# `parity::assert_codebook_parity()` for the full id/domain bijection (call it at
22+
# consumer startup; also asserted by this crate's tests = the CI gate). A build
23+
# WITHOUT this crate uses the contract's zero-dep mirror + the bare ClassView
24+
# trait. OGAR never depends on the lance-graph ENGINE — only the zero-dep contract.
2325
#
24-
# ONE contract source: this crate AND ogar-class-view both resolve
25-
# `lance-graph-contract` to git `AdaWorldAPI/lance-graph#main` (which carries
26-
# `ogar_codebook` since PR #563) — so `OgarClassView`'s `impl ClassView` is for
27-
# the SAME contract the parity-guard checks. No [patch] needed (the symbiont
28-
# pattern: align on one source rather than redirect).
26+
# ── ONE contract source (codex P2, PR #564) ──
27+
# The canonical `lance-graph-contract` in-repo is the PATH copy (`crates/
28+
# lance-graph-contract`) — what `lance-graph` and `symbiont` already path-dep.
29+
# `ogar-class-view` (in the OGAR repo) hard-codes a `git` dep on
30+
# `AdaWorldAPI/lance-graph#main` for ITS standalone build; Cargo treats path and
31+
# git as DISTINCT crates even at the same version, so `OgarClassView` would impl a
32+
# DIFFERENT `ClassView` than the engine expects. The `[patch]` below redirects
33+
# that transitive git contract onto the SAME path copy, so this crate's standalone
34+
# build has exactly one contract source = the path copy.
35+
#
36+
# CONSUMER REQUIREMENT (cargo limitation): `[patch]` only applies in the WORKSPACE
37+
# ROOT. When an in-repo workspace root (e.g. `crates/symbiont`) adds
38+
# `lance-graph-ogar`, THIS crate's `[patch]` is ignored — that root MUST repeat:
39+
# [patch."https://github.com/AdaWorldAPI/lance-graph"]
40+
# lance-graph-contract = { path = "../lance-graph-contract" }
41+
# to unify ogar-class-view's transitive git contract onto its path copy. Without
42+
# it the OgarClassView `impl ClassView` won't typecheck against the engine's.
2943
#
3044
# Build/verify: cargo test --manifest-path crates/lance-graph-ogar/Cargo.toml
3145
# Full DO arm : cargo test --manifest-path crates/lance-graph-ogar/Cargo.toml \
@@ -53,9 +67,10 @@ serde = ["ogar-vocab/serde", "ogar-adapter-surrealql/serde"]
5367

5468
[dependencies]
5569
# Contract surface (zero-dep): ClassView / ObjectView / ClassId / NodeGuid + the
56-
# ogar_codebook wire-compat mirror the parity-guard checks. git main == the SAME
57-
# source ogar-class-view git-deps, so there is exactly ONE lance-graph-contract.
58-
lance-graph-contract = { git = "https://github.com/AdaWorldAPI/lance-graph", branch = "main" }
70+
# ogar_codebook wire-compat mirror the parity-guard checks. PATH copy = the
71+
# canonical in-repo source (same as lance-graph / symbiont); the [patch] below
72+
# folds ogar-class-view's transitive git contract onto it = ONE source.
73+
lance-graph-contract = { path = "../lance-graph-contract" }
5974

6075
# ── OGAR Active-Record forks: git deps @ main (the canonical superset; matches
6176
# symbiont's pins so they resolve to ONE source in the golden image) ──
@@ -65,3 +80,12 @@ ogar-ontology = { git = "https://github.com/AdaWorldAPI/OGAR", branch = "main" }
6580
# default features only = the light emit() DDL formatter (no surrealdb tree);
6681
# the parser half is opt-in via this crate's `surrealql-parser` feature.
6782
ogar-adapter-surrealql = { git = "https://github.com/AdaWorldAPI/OGAR", branch = "main" }
83+
84+
# Fold ogar-class-view's transitive `lance-graph-contract` (git
85+
# AdaWorldAPI/lance-graph#main) onto the SAME path copy this crate uses, so there
86+
# is exactly ONE contract crate and `OgarClassView`'s `impl ClassView` is for it
87+
# (codex P2, PR #564). Applies in THIS crate's standalone build (its own
88+
# [workspace] root); an in-repo workspace root that adds this crate must repeat
89+
# the patch (see the CONSUMER REQUIREMENT note in the header).
90+
[patch."https://github.com/AdaWorldAPI/lance-graph"]
91+
lance-graph-contract = { path = "../lance-graph-contract" }

crates/lance-graph-ogar/src/lib.rs

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,20 @@
3737
//! A build graph that pulls THIS crate (the golden image via `symbiont`, or any
3838
//! AR-aware consumer — q2, medcare, …) gets the **real** OGAR `Class`/`ClassView`/
3939
//! codebook (including [`ogar_vocab`]'s full curator-alias normalizer, so OGAR is
40-
//! never dumbed down) **plus** the [`parity`] guard that fails the build if the
41-
//! contract's lean `ogar_codebook` mirror ever drifts from OGAR's authoritative
42-
//! `class_ids::ALL`. One contract source: this crate and `ogar-class-view` both
43-
//! resolve `lance-graph-contract` to git `AdaWorldAPI/lance-graph#main` (which
44-
//! carries `ogar_codebook` since PR #563), so the `OgarClassView` `impl ClassView`
45-
//! is for the SAME contract the guard checks.
40+
//! never dumbed down) **plus** the [`parity`] guard. The guard fires at two depths
41+
//! so it cannot be silently bypassed (codex P2, PR #564):
42+
//! - a **compile-time length fuse** ([`parity`] `const _`) that fails ANY build
43+
//! (`cargo build` included) if the mirror and `ogar_vocab::class_ids::ALL` have
44+
//! a different concept count — the most common drift (add/remove a concept);
45+
//! - a **runtime full-bijection** check ([`parity::assert_codebook_parity`]) for
46+
//! id + domain agreement, asserted by this crate's tests (the CI gate) and
47+
//! callable at consumer startup.
48+
//!
49+
//! One contract source: this crate path-deps `lance-graph-contract` (the canonical
50+
//! in-repo copy) and a `[patch]` folds `ogar-class-view`'s transitive *git*
51+
//! contract onto the SAME path copy, so the `OgarClassView` `impl ClassView` is for
52+
//! the contract the guard checks (an in-repo workspace root adding this crate must
53+
//! repeat that patch — see the manifest CONSUMER REQUIREMENT note).
4654
//!
4755
//! # The OGIT ↔ OGAR seam
4856
//!
@@ -72,13 +80,24 @@ pub use ogar_vocab::Class;
7280

7381
/// Codebook parity-guard — the drift fuse between OGAR's authoritative codebook
7482
/// (`ogar_vocab::class_ids::ALL`) and the contract's zero-dep wire mirror
75-
/// (`lance_graph_contract::ogar_codebook::CODEBOOK`). Compiled (and tested) only
76-
/// when this crate is in the build graph, so any OGAR-present build (the golden
77-
/// image, AR-aware consumers) fails fast on divergence; OGAR-absent builds carry
78-
/// the mirror alone and never need the check.
83+
/// (`lance_graph_contract::ogar_codebook::CODEBOOK`). Two depths so it cannot be
84+
/// silently bypassed (codex P2, PR #564): a [`COUNT_FUSE`] **compile-time** assert
85+
/// that fires in ANY build, plus [`assert_codebook_parity`] for the runtime full
86+
/// id/domain bijection (tested here = CI gate; call at consumer startup too). When
87+
/// this crate is absent, the contract's mirror stands alone and needs no check.
7988
pub mod parity {
8089
use lance_graph_contract::ogar_codebook as mirror;
8190

91+
/// **Compile-time length fuse.** Fails the build — `cargo build`, not just
92+
/// `cargo test` — if the contract mirror and OGAR's authoritative
93+
/// `class_ids::ALL` carry a different number of concepts (add/remove drift).
94+
/// The full id/domain bijection is the runtime [`assert_codebook_parity`].
95+
pub const COUNT_FUSE: () = assert!(
96+
mirror::CODEBOOK.len() == ogar_vocab::class_ids::ALL.len(),
97+
"ogar_codebook mirror drifted from ogar_vocab::class_ids::ALL (concept count mismatch) — \
98+
update lance_graph_contract::ogar_codebook::CODEBOOK to match OGAR",
99+
);
100+
82101
/// Whether OGAR's domain for `id` agrees with the contract mirror's. Both
83102
/// enums are structurally identical (`id >> 8` discriminant); compared by a
84103
/// total match so a new OGAR domain variant trips this (`#[non_exhaustive]`).

0 commit comments

Comments
 (0)