From 64c858ca77c2b529023c97f6017f1b08cc33e11b Mon Sep 17 00:00:00 2001 From: "Claude (OGAR session)" Date: Fri, 5 Jun 2026 07:25:18 +0000 Subject: [PATCH] floor: fix non-exhaustive errors in surrealql adapter + add compile CI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit main has been silently uncompilable on `cargo check --workspace --all-targets` since #15 closed (which added `#[non_exhaustive]` to the vocab enums). No compile CI to catch it, so every subsequent merge was verified on vibes. This lands the floor. Three parts: 1. `crates/ogar-adapter-surrealql/src/lib.rs` - Two wildcard arms (`AssociationKind`, `EnumSource`) — required by `#[non_exhaustive]`. The four/three existing arms cover every variant defined today; the wildcards `unreachable!` with a message so adding a vocab variant produces a clean panic at first emit instead of a silent miscompile. - Three test-side `EnumDecl { … }` struct expressions replaced with `EnumDecl::new(…)` + field assignment (the struct is `#[non_exhaustive]` too — direct construction is forbidden from outside the crate). - Dead `EnumVariant` import removed. 2. `.github/workflows/ci.yml` - Minimal compile CI: `cargo check --workspace --all-targets` + `cargo test --workspace`, pinned to Rust 1.95.0 per `rust-toolchain.toml`, with `Swatinem/rust-cache` for re-runs. - Runs on `push: main` and every PR. - This is the floor — once it's green on main, any future PR that breaks the workspace fails its own CI instead of merging. 3. `docs/ARCHITECTURAL-DECISIONS-2026-06-04.md` - ADR-022 (The Firewall) reception receipts — pinning the cross-session convergence (2026-06-05) that triangulated the inner/outer split: OGAR docs (#26), Rubicon implementation (bardioc PR #17), runtime architectural handover (bardioc #18 + lance-graph #470). Three independent landings now share the inner = trie-append / outer = `commit_event` boundary; weakening The Firewall now requires re-coordinating across all three surfaces — exactly the friction the change-policy clause was designed to produce. Verified locally: `cargo check --workspace --all-targets` clean; `cargo test --workspace` = 80/80 passing + 8/8 doctests. https://claude.ai/code/session_01PBTGaPCSnnt6u3pjXpbLwY --- .github/workflows/ci.yml | 32 +++++++++++++++ crates/ogar-adapter-surrealql/src/lib.rs | 47 +++++++++++----------- docs/ARCHITECTURAL-DECISIONS-2026-06-04.md | 37 +++++++++++++++++ 3 files changed, 93 insertions(+), 23 deletions(-) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..10d07a3 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,32 @@ +name: ci + +on: + push: + branches: [main] + pull_request: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + CARGO_TERM_COLOR: always + CARGO_INCREMENTAL: 0 + +jobs: + check: + name: cargo check + test + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@v4 + - name: Install Rust toolchain (per rust-toolchain.toml) + uses: dtolnay/rust-toolchain@master + with: + toolchain: 1.95.0 + components: rustfmt, clippy + - uses: Swatinem/rust-cache@v2 + - name: cargo check --workspace --all-targets + run: cargo check --workspace --all-targets + - name: cargo test --workspace + run: cargo test --workspace diff --git a/crates/ogar-adapter-surrealql/src/lib.rs b/crates/ogar-adapter-surrealql/src/lib.rs index 3f4579b..2bdae9f 100644 --- a/crates/ogar-adapter-surrealql/src/lib.rs +++ b/crates/ogar-adapter-surrealql/src/lib.rs @@ -296,6 +296,11 @@ fn emit_field_assoc(table: &str, assoc: &Association, out: &mut String) { table, assoc.kind, assoc.name )); } + // `AssociationKind` is `#[non_exhaustive]` in `ogar-vocab`; the four + // arms above cover every variant defined today. The wildcard exists + // only so adding a variant in `ogar-vocab` produces a clean + // panic-on-first-emit instead of a silent miscompile elsewhere. + _ => unreachable!("vocab variant added without adapter update: AssociationKind"), } } @@ -337,6 +342,11 @@ fn emit_field_enum(table: &str, enum_decl: &EnumDecl, out: &mut String) { enum_decl.column, table, escaped )); } + // `EnumSource` is `#[non_exhaustive]` in `ogar-vocab`; the three arms + // above cover every variant defined today. The wildcard exists only + // so adding a variant in `ogar-vocab` produces a clean panic-on-first + // -emit instead of a silent miscompile elsewhere. + _ => unreachable!("vocab variant added without adapter update: EnumSource"), } } @@ -377,7 +387,7 @@ fn surreal_string_literal(s: &str) -> String { #[cfg(test)] mod tests { use super::*; - use ogar_vocab::{EnumVariant, Language}; + use ogar_vocab::Language; #[test] fn emit_minimal_class_produces_define_table() { @@ -438,14 +448,11 @@ mod tests { #[test] fn emit_class_with_static_enum_renders_assert_in_list() { let mut c = Class::new("ticket"); - let status = EnumDecl { - column: "status".into(), - source: ogar_vocab::EnumSource::Static(vec![ - ("open".into(), "Open".into()), - ("closed".into(), "Closed".into()), - ]), - scopes_disabled: None, - }; + let mut status = EnumDecl::new("status"); + status.source = ogar_vocab::EnumSource::Static(vec![ + ("open".into(), "Open".into()), + ("closed".into(), "Closed".into()), + ]); c.enums.push(status); let ddl = emit_surrealql_ddl(&[c]); assert!( @@ -457,13 +464,10 @@ mod tests { #[test] fn emit_class_with_add_enum_emits_parent_selection_marker() { let mut c = Class::new("account_move_line"); - let parent_enum = EnumDecl { - column: "state".into(), - source: ogar_vocab::EnumSource::Add { - items: vec![("paid".into(), "Paid".into())], - parent_selection: "account.move.line".into(), - }, - scopes_disabled: None, + let mut parent_enum = EnumDecl::new("state"); + parent_enum.source = ogar_vocab::EnumSource::Add { + items: vec![("paid".into(), "Paid".into())], + parent_selection: "account.move.line".into(), }; c.enums.push(parent_enum); let ddl = emit_surrealql_ddl(&[c]); @@ -477,13 +481,10 @@ mod tests { #[test] fn emit_class_with_computed_enum_emits_lambda_marker() { let mut c = Class::new("address"); - let country_enum = EnumDecl { - column: "country".into(), - source: ogar_vocab::EnumSource::Computed( - "lambda self: self.env[\'res.country\']...".into(), - ), - scopes_disabled: None, - }; + let mut country_enum = EnumDecl::new("country"); + country_enum.source = ogar_vocab::EnumSource::Computed( + "lambda self: self.env[\'res.country\']...".into(), + ); c.enums.push(country_enum); let ddl = emit_surrealql_ddl(&[c]); assert!( diff --git a/docs/ARCHITECTURAL-DECISIONS-2026-06-04.md b/docs/ARCHITECTURAL-DECISIONS-2026-06-04.md index cade94b..007df87 100644 --- a/docs/ARCHITECTURAL-DECISIONS-2026-06-04.md +++ b/docs/ARCHITECTURAL-DECISIONS-2026-06-04.md @@ -1021,6 +1021,43 @@ crossing is fine; the same cost per inner operation is forbidden. (`knowable_from` — outer firewall seam), `lance-graph-contract::ExternalMembrane`. - Precedent: MedCare-rs (`Membrane` + `LazyLock`), Woa-rs (SeaORM backend). +**Reception receipts — cross-session convergence (2026-06-05).** The +runtime session — working independently on the BindSpace dissolution +and the qualia codebook — arrived at the same inner/outer split this +ADR pins, without coordination on the surface itself. Three independent +landings now triangulate The Firewall: + +- **OGAR-side pin** (this ADR + `docs/THE-FIREWALL.md`): the boundary is + absolute; inner = compile-time HHTL, outer = contract-trait pluggable; + litmus = "crypto on post stamps". +- **Runtime-side implementation** (bardioc PR #17, Rubicon Phases 1-5, + 33 tests): `LanceMembraneWriter` carries the outer write surface, with + the hot path (Rubicon state-machine dispatch) sitting inside the + firewall. +- **Runtime-side architectural handover** (bardioc PR #18 + + lance-graph PR #470, `BINDSPACE_DISSOLUTION_HANDOVER.md`): the + runtime session independently named the same split — *"Rubicon's + `LanceMembrane::commit_event` keyed on `inv.object_instance` becomes + a trie append"* (inner) over the outer `commit_event` write — and + cited `HEALTHCARE-TRANSCODING.md §3` (the row-level `_effectiveReaders` + mask) as the model for task-scoped qualia activation via `QualiaScope`. + +Triangulation matters because architectural axioms are only load- +bearing if multiple sessions can re-derive them. Three sessions +(OGAR docs, Rubicon implementation, runtime handover) now share the +inner = trie-append / outer = `commit_event` boundary as common ground. +Weakening The Firewall now requires re-coordinating across all three +surfaces — exactly the friction this ADR's change-policy clause was +designed to produce. + +**Reception references.** +- bardioc PR #17 (Rubicon Phases 1-5; the Implementation Receipts + section below already cites its commits). +- bardioc PR #18 (`BINDSPACE_DISSOLUTION_HANDOVER.md` — the canonical + architectural-delta doc). +- lance-graph PR #470 (`.claude/handovers/2026-06-05-0445-bardioc-to- + lance-graph-bindspace-arch-delta.md` — the lance-graph-side pointer). + ## Implementation receipts — ADR ↔ commit cross-reference > **Added in follow-up addendum (2026-06-05).** Records the implementation