diff --git a/.claude/board/EPIPHANIES.md b/.claude/board/EPIPHANIES.md index 819a4358..9ab33981 100644 --- a/.claude/board/EPIPHANIES.md +++ b/.claude/board/EPIPHANIES.md @@ -1,3 +1,32 @@ +## 2026-06-19 — E-OGAR-AR-SHAPE-REHOME — the `ar_shape` module was a PARALLEL AR registry in the wrong repo (the od-ontology construction error, repeated); OGAR's `ogar-vocab` already IS the canonical registry — lance-graph does Odoo EXTRACTION that resolves to OGAR's codebook, it does not RE-DERIVE the registry + +**Status:** FINDING (construction-error correction; operator-flagged 2026-06-19; #552 closed, module reverted from lance-graph). **Supersedes the CODE-HOME claim of `E-OGAR-AR-SHAPE-SMOKE-1..6` below** — their *findings* (cross-curator node/vocabulary/edge/mixin convergence) hold and are real, but the *code that proved them belongs in `AdaWorldAPI/OGAR`, not `lance-graph-ontology`*. The module was reverted; this entry records why so a future session does not rebuild it here. + +**The error (the same pattern called out at the very start of this arc).** The operator's opening critique of this whole line of work was: *"using flat od-ontology and not touching ar_shape is a huge construction error… a parallel object model duplicating what the typed Core already held."* I then did the inverse-but-identical mistake: I built `lance-graph-ontology::ar_shape` — a `CanonicalConcept` enum + codebook ids + `concept_of_token` resolver + `concept_edges` + `synergy_registry_one_shot` + per-curator codebooks — **as a parallel generic-AR registry in lance-graph**, when `AdaWorldAPI/OGAR`'s `ogar-vocab` (3 383 LOC) ALREADY IS that registry, richer. + +**The duplication, line by line (verified against OGAR@156c016):** + +| `ar_shape` (lance-graph, reverted) | `ogar-vocab` (OGAR, canonical) | +|---|---| +| `CanonicalConcept` enum + `codebook_id()` | `const CODEBOOK` + `canonical_concept_id(name) -> Option` | +| `concept_of_token(token)` | `canonical_concept(name) -> String` (richer alias arms) | +| `synergy_registry_one_shot` | `wire_synergies(classes) -> Vec` + `Synergy`/`SynergyMember` | +| `concept_edges` / `ConceptEdge` | `Association` / `AssociationKind` on the full `Class` | +| `Domain` (I drafted then reverted) | `ConceptDomain` + `canonical_concept_domain(id)` (the 0xDDCC encoding) | +| the 6 commerce concepts `0x0201`–`0x0206` | **identical ids**, landed by OGAR PR #64 ("commerce/ERP canonical wave — 6 cross-curator concepts (OSB ↔ Odoo)"), with full `Class` (attrs/methods/actions), not lexical detectors | + +OGAR's `ogar-from-rails` even states the intended split in a source comment: *"the Odoo-side extraction lives in the parallel session"* — i.e. **OGAR owns the registry; lance-graph does the Odoo extraction; they MEET at `canonical_concept_id`** (a Rails label and an Odoo label both resolve to the same `u16`). I re-implemented the registry instead of consuming it. + +**The correct architecture (what lance-graph's contribution should have been).** lance-graph already has the Odoo half: `odoo_blueprint` (the typed Odoo Core) + `tools/odoo-blueprint-extractor` + `crates/lance-graph/src/graph/spo/odoo_ontology.spo.ndjson`. The *only* legitimate lance-graph addition would have been a thin resolver mapping an Odoo class label to OGAR's `canonical_concept_id` — and even that mostly exists. **No `CanonicalConcept` enum, no codebooks, no fixtures belonged in lance-graph.** The detection is generic AR = OGAR; the Odoo extraction is lance-graph; they meet at the codebook. + +**What was genuinely net-new (and where it goes).** OGAR's commerce block stops at `0x0206` (`currency_policy`). The **five SMOKE-5 concepts — `SalesOrder`, `SalesOrderLine`, `FulfillmentFlow`, `InventoryMovement`, `ProductOffering`** (Spree + Odoo evidence) — are NOT yet in OGAR's codebook. **Those are the only re-homeable contribution**, and they belong in OGAR's `0x0207`–`0x020B` commerce extension + a Spree curator in `ogar-from-rails`, in OGAR's full-`Class` pattern (matching `commercial_line_item()` etc.) — NOT as lance-graph lexical detectors. Queued for OGAR; the other session owns that lane. The cross-curator edge-convergence *finding* + the mixin-as-family-node *finding* are real but OGAR's `Association` + `wire_synergies` + the `project_actor` STI-collapse already carry those shapes. + +**The lesson (generalize the guard).** Before building ANY canonical-concept registry, resolver, codebook, or synergy detector, **check OGAR first** — `ogar-vocab` is the single source of truth for AR canonical concepts; `ogar-from-rails`/`ogar-from-ruff`/`ogar-from-elixir` are the harvest frontends; the `ogar-adapter-*` crates are egress. A consumer repo (lance-graph, woa-rs, odoo-rs) RESOLVES to OGAR's codebook; it never re-derives it. The 30-turn rediscovery tax this session paid is the cost of not checking the curated OGAR surface before writing 2 568 lines of duplicate. + +**Cross-refs:** `AdaWorldAPI/OGAR` `ogar-vocab` (the canonical registry this duplicated) + `ogar-from-rails` ("Odoo-side extraction lives in the parallel session") + PR #64 (the commerce concepts, already landed); the reverted `lance-graph-ontology::ar_shape` (#552, closed); `E-ODOO-CORE-FIRST-STRUCTURAL` (the original "don't build a parallel model" doctrine this re-violated); `E-OGAR-AR-SHAPE-SMOKE-1..6` (findings preserved, code-home corrected); `docs/OGAR_AR_SHAPE_ENDGAME.md` (the doctrine — correctly says OGAR is the compiler; I just put the code in the wrong consumer). + +--- + ## 2026-06-19 — E-FAMILY-BASIN-WEYL-HOP-LOCAL-AT-CRISP-TIER — REINSTATEMENT (tier-scoped) of `E-OUTAGE-CASCADE-IS-NON-LOCAL`: WITH the family-basin partition, a within-basin perturbation is block-localized (95.7 % containment, within/seam ratio 1.54) at the **crisp top split**, so multi-hop Weyl IS hop-local there; finer tiers leak. The earlier non-locality was the *un-partitioned* global solve. (Davis-Kahan is the *mechanism* — see body — NOT the numeric evidence; the gate is the containment ratio.) **Status:** FINDING (measured, real ES PyPSA data; probe `perturbation-sim/examples/family_basin_weyl_multihop.rs`). **Tier-scoped reinstatement** of the reach claim that `E-OUTAGE-CASCADE-IS-NON-LOCAL` had corrected. Operator hypothesis: "with family basin it works now with weyl multihop." Confirmed — at the crisp tier only. @@ -17,6 +46,43 @@ At the **crisp top split** a within-basin perturbation stays **95.7 % contained* **The three-axis close (a "surge" decomposes, and each axis owns one aspect):** WHERE it breaks = CHAODA anomaly (manifold repulsion, `ndarray::hpc::clam`); HOW MUCH = Weyl magnitude (probes A–D, [G] exact in code); HOW it spreads = **family-basin block-localized Weyl multi-hop, hop-local at the crisp tier** (this finding) + the ketchup yield as the seam gate. The family-basin layer (`E-BASIN-IS-A-NODE`) is the keystone that block-diagonalizes the Laplacian so per-basin Weyl chains seam-to-seam. **Self-correction (process):** the probe's first verdict rubber-stamped a 0.044 within-vs-seam gap + a **vacuous Davis-Kahan bound (2199)** as "SUPPORTED" — the same confirmation-bias trap. Tightened the gate to per-tier within ≥ 0.70 AND within/seam ratio ≥ 1.30 AND Weyl, dropped the DK bound as evidence (it is uninformative when the eigengap is tiny). Under the honest gate only HEEL passes — which is the correct, nuanced result. Cross-refs: `E-OUTAGE-CASCADE-IS-NON-LOCAL` (the claim reinstated), `E-BASIN-IS-A-NODE` (the family-basin keystone), `perturbation-sim::{spectral_perturbation, hhtl_keys}`, probes A–E (the spectral foundation, real PyPSA), the "without family nodes" tier table. +## 2026-06-19 — E-OGAR-AR-SHAPE-SMOKE-6 — a mixin IS a family/group node: Rails `include` and Odoo `_inherit` are the SAME `members`/`memberof` primitive from lance-graph #545..#551 — RESOLVES the earlier-flagged "Odoo _inherit is non-AR" claim (it was wrong) + +**Status:** FINDING (operator nudge, 2026-06-19; 35/35 ar_shape tests green, ar_shape clippy-clean). **Corrects an error I posted earlier this session.** When asked "does it make sense to use the Rails-shaped spine to verify Odoo AR-shapedness," I answered yes but flagged Odoo's `_inherit` mixin composition as "a non-AR shape with no Rails analog... closer to Smalltalk/Ruby modules than to AR." The operator nudge: *"the family nodes introduced in lance-graph 545..551 could serve as mixin — group.memberof/members where group is the mixin node."* That dissolves the divergence — the earlier claim was wrong. + +**The resolution.** A mixin IS a family/group node (per `E-BASIN-IS-A-NODE` / `E-FAMILY-NODE-IS-META-AWARENESS`, lance-graph #545..#551 `graph::mailbox_scan::{members, memberof, BasinOf}`). `group.members` = the classes that include the mixin; `class.memberof` = the mixin group. Rails `include ModuleX` (concerns) and Odoo `_inherit = ['mail.thread', ...]` are NOT different architectures — they are the SAME `members`/`memberof` edge into a group node. The Rails analog of Odoo `_inherit` is exactly `include`; both lower to family-node membership. Odoo is AR-shape-VERIFIED on mixins, not divergent. + +**Grounded in the harvest (not asserted):** +- OSB (Rails) carries **37 `includes_module` triples**: `Client include PublicActivity::Model`, `Estimate include {PublicActivity::Model, Trackstamps, DateFormats}`. +- Odoo carries **166 `inherits_from` triples**: `mail_thread` is a group node with **70+ members** (`sale_order`, `account_account`, `purchase_order`, `res_company`, `stock_picking`, …); `account_move` rides `mail_activity_mixin` + `sequence_mixin` (the harvest's faithful distinction — account_move is NOT a direct mail_thread member, and the test preserves that). +- **Cross-curator semantic convergence:** OSB `PublicActivity::Model` (activity tracking) ≈ Odoo `mail_thread` / `mail_activity_mixin` (chatter + activities). Both curators independently grew an activity-tracking mixin group — the mixin-as-family-node pattern converges even though specific mixin names differ. + +**The ≥2-member filter IS the family-node fan-out.** `shared_mixin_groups(members, 2)` keeps only groups with ≥2 members — a genuinely shared mixin (shared behaviour). A single-member "group" (`account_bank_statement_line inherits_from account_move`) is an STI base / model EXTENSION, not a mixin, and is correctly excluded. This is the same structural distinction `members(basin)` draws in #549: a basin node fans out to its children; a mixin group fans out to its members; a single-member parent is an extension, not a group. + +**The code (`mixin_members` + `shared_mixin_groups` + 4 tests):** `mixin_members(triples, ns, is_rails) -> BTreeMap>` reads `includes_module` (Rails) or `inherits_from` (Odoo), namespace-strips, returns the `members` direction (the `memberof` inverse is the transpose). `shared_mixin_groups(members, min)` applies the fan-out filter. Tests: `odoo_mail_thread_is_a_family_group_node_with_many_members`, `osb_rails_public_activity_model_is_a_family_group_node`, `rails_include_and_odoo_inherit_are_the_same_family_node_primitive` (the divergence-resolution test), `single_member_extension_is_not_a_mixin_group` (the fan-out honesty test). + +**Why this matters for the spine answer.** It sharpens the Rails-as-calcification-anchor doctrine: Rails defines AR; Odoo gets graded against it. The mixin case looked like an Odoo divergence — but mapped onto the family-node substrate, it's a clean cross-curator match. The lesson: an apparent "Odoo non-AR divergence" should first be checked against the lance-graph substrate primitives (#545..#551 `members`/`memberof`, the family-node tree) before being called a divergence. The substrate already had the home for it. The mixin group node also carries the shared behaviour down to members — which is `E-FAMILY-NODE-IS-META-AWARENESS` exactly (the parent node IS the coarse summary its members inherit), now instantiated for ERP mixins rather than Walsh bands. + +**Cross-refs:** `crates/lance-graph-ontology/src/ar_shape.rs` (`mixin_members` + `shared_mixin_groups` + 4 tests); `E-BASIN-IS-A-NODE` + `E-FAMILY-NODE-IS-META-AWARENESS` + `E-GUID-SELF-ROUTES-THE-BASIN-TREE` (the #545..#551 family-node arc this maps onto); `graph::mailbox_scan::{members, memberof}` (lance-graph #549, the substrate primitive); `E-OGAR-AR-SHAPE-SMOKE-5` (the concept-edge AST test this extends — mixin membership is the inheritance-edge complement to the composition-edge concept graph); `AdaWorldAPI/OGAR` CODEBOOK (`project_actor` STI-collapse used the same shape on User/Principal). + +--- + +## 2026-06-19 — E-OGAR-AR-SHAPE-SMOKE-5 — the ERP AST test passes at EDGE level, not just node level: OSB (Rails) and Odoo emit the SAME canonical concept-GRAPH (`CommercialLineItem → CommercialDocument`, `→ TaxPolicy`; `CommercialDocument → BillingParty`) despite different class names, field names, AND predicate vocabularies + +**Status:** FINDING (operator-directed "odoo vs rails based ERP AST test", 2026-06-19; 31/31 ar_shape tests green, ar_shape clippy-clean). The synergy work so far proved NAME-level convergence (a class IRI → a `CanonicalConcept`). This entry lands the deeper, real test: **EDGE-level convergence** — the canonical concept GRAPH (concept→concept relations) is the same across a Rails-based ERP and Odoo, which is what makes it an *AST*, not a label table. + +**The test (`concept_edges` + 3 tests):** `concept_of_token(token) -> Option` resolves a single relation token — whether an Odoo comodel class name (`account_tax`, `account_move`, `res_partner`) OR a Rails relation leaf (`tax1`, `invoice`, `client`, `item`) — to its concept via the same lexical hints the 11 class detectors use, priority-ordered so `*line*`/`tax`/`stock_move` resolve before the bare document arms. `concept_edges(triples, ns, is_rails)` runs the per-curator OGIT codebook (`translate_rails_to_ogit` / `translate_odoo_to_ogit`), resolves BOTH endpoints of each canonical relation to concepts, and returns the `BTreeSet<(from, to)>` edge set (self-edges dropped). + +**The convergence proven on real corpora:** +- **`CommercialLineItem → CommercialDocument`** — OSB `InvoiceLineItem.invoice` (Rails `declares_association`, leaf "invoice") AND Odoo `account_move_line.move_id → account.move` (Odoo `target`). Different field name, different predicate, **same edge**. +- **`CommercialLineItem → TaxPolicy`** — OSB `InvoiceLineItem.{tax1,tax2}` (two named FKs) AND Odoo `account_move_line.tax_ids → account.tax` (one M2M). Different cardinality, different field, **same edge**. +- **`CommercialDocument → BillingParty`** — OSB `Invoice belongs_to :client` AND Odoo `account_move → partner_id → res.partner`. Proves the convergence isn't limited to the line-item node — it's the whole sub-graph. + +**Why this is THE AST test (not the previous ones).** Node-level convergence (SMOKE-1..4) shows two curators NAME the same concepts. Edge-level convergence shows two curators STRUCTURE those concepts identically — the line item is a member of a document, the document belongs to a party, the line carries a tax. That structural sub-graph is curator-independent: strip the Rails/Odoo syntax (class names, field names, `declares_association` vs `target`) and the **same business AST remains**. This is doctrine §2 "labels are leaf detail; the SHAPE is what overlaps" proven at the relation level, not just the class level — the strongest cash-out yet of OGAR-is-the-compiler (the concept-graph IS the compiled output; the curators are interchangeable front-ends). + +**Scope (carried).** The detectors stay lexical (token ends-with/contains hints); `concept_of_token` returns `None` for real-but-unpromoted relation targets (`estimate`, `uom`, `analytic_account`) — honest, not fabricated. The edge set is the intersection of what BOTH curators emit; single-curator edges are visible per-curator but the *shared* sub-graph is the AST. Next deepening (deferred): edge *cardinality/direction* convergence (M2O vs O2M vs M2M), and wiring `concept_edges` into `synergy_registry_one_shot` so the one-shot table carries edges, not just nodes. + +**Cross-refs:** `crates/lance-graph-ontology/src/ar_shape.rs` (`concept_of_token` + `concept_edges` + `ConceptEdge`/`ConceptDetector` aliases + 3 tests); `E-OGAR-AR-SHAPE-SMOKE-3` (the OGIT canonical codebooks this builds on); `E-OGAR-AR-SHAPE-SMOKE-4` (the node-level sibling concepts); `docs/OGAR_AR_SHAPE_ENDGAME.md` §2 correction 4 (labels-are-leaf-detail, now proven at edge level); `AdaWorldAPI/OGAR` CODEBOOK (the concept-edges are the family-edge structure OGAR's canonical classes already encode — e.g. `commercial_line_item` family-edges to `commercial_document` + `tax_policy`). --- @@ -86,6 +152,99 @@ The local-scan `memberof` (#this-branch) is the **in-mailbox special case** of " **Three threads are ONE structure:** basin-tree (1→4→16…) = Morton tile pyramid (quadtree subdivision) = `perturbation-sim` L1-L4 cascade levels = the field perturbation-learning runs over. Distance = hop count = pyramid level = cascade round — **one number, three readings**. **Wiring (gated on the 5+3 council for the SoA-ownership commitment):** add `row_for_member_index` to the contract (basin-node → member row); wire the EdgeBlock out-family slot → sibling basin-node via ClassView (Options 1+2); reclassify **CHAODA as a unary `node_anomaly`** (point↔manifold LFD), NOT a pairwise `DistanceMeans` — it never belonged in the hop-distance dispatch. The `node_distance(PrefixDepth)` tree-hop is already the basin-tree distance; no new means needed for the structural tier. Cross-refs: `E-PANCAKES-IS-RADIX-IS-HHTL` (radix subtree = basin), `E-COARSE-QUANTIZER-IS-SCALE-FREE-ROUTER` (basin-node = IVF coarse centroid = parent SoA), `E-CLAM-IS-THE-MANIFOLD-ENGINE` (CHAODA = unary anomaly), `E-WHT-META-AWARENESS-AND-KRONECKER-LOOKUP` (pyramid energy = the field summary), `E-GUID-IS-THE-GRAPH`, canon node 512 B, `perturbation-sim::{sketch::walsh_pyramid_energy, chaoda}`, OGAR "256×256 centroid tile" + "perturbation = (exponent, location, phase, magnitude)". +## 2026-06-19 — E-OGAR-AR-SHAPE-SMOKE-4 — five more OSB↔Odoo synergies land on real corpora: TaxPolicy / CommercialDocument / BillingParty / CurrencyPolicy / PaymentRecord (lexical class-shape on OGIT-declared types); CanonicalConcept enum at 6 variants + +**Status:** FINDING (operator-directed "continue with opensource-billing <> odoo", 2026-06-19; 19/19 ar_shape tests green including 5 new sibling-concept corpus-driven tests). Extends `E-OGAR-AR-SHAPE-SMOKE-3` (OGIT canonical + codebooks) with five more harvest-proven `CanonicalConcept` variants per the operator's named smoke targets. + +**What landed:** + +- `CanonicalConcept` enum extended from 1 → 6 variants. Each new variant — `CommercialDocument`, `TaxPolicy`, `BillingParty`, `PaymentRecord`, `CurrencyPolicy` — corresponds to an operator-named concept from the smoke pass spec, and each is gated by ≥2-curator evidence on the real corpora (the OSB harvest fixture + the workspace Odoo manifest), not pre-emptively added. +- Shared `declared_classes(triples, ns) -> BTreeSet` helper returns class IRIs that surface as `(class, rdf:type, ogit:ObjectType)` — filters out method / field IRIs. +- 5 sibling lexical-shape detectors built on the helper: + - `classes_matching_commercial_document_shape_canonical` — lowercase ends with `invoice`/`move`/`order` AND does NOT contain `line` (the line filter discriminates `InvoiceLineItem` / `account_move_line` from documents). Surfaces `Invoice` (OSB) + `account_move` (Odoo). + - `classes_matching_tax_policy_shape_canonical` — lowercase ends with `tax`. Surfaces `Tax` + `account_tax`. Filters out `TaxGroup` / `account_tax_group` (lowercased neither ends with `tax`). + - `classes_matching_billing_party_shape_canonical` — lowercase ends with `client`/`customer`/`partner`. Surfaces `Client` + `res_partner`. + - `classes_matching_currency_policy_shape_canonical` — lowercase ends with `currency`. Surfaces `Currency` + `res_currency`. + - `classes_matching_payment_record_shape_canonical` — lowercase ends with `payment`. Surfaces `Payment` + `account_payment` (also `CreditPayment` as expected sub-type; downstream ranking picks the primary). +- 5 corpus-driven tests with names matching the operator's convention (e.g. `open_source_billing_tax_and_odoo_tax_overlap_as_tax_policy`). Each loads the OSB ndjson fixture (`tests/fixtures/osb_ruby_spo.ndjson`, 1195 triples) + the workspace Odoo manifest (`crates/lance-graph/src/graph/spo/odoo_ontology.spo.ndjson`, 2.8 MB) and asserts the expected class IRI appears on each side. + +**Scope discipline (carried).** Lexical class-shape is the minimal viable detector. Structural-shape refinement (incoming OGIT canonical relations FROM line-items for TaxPolicy; outgoing has_many to line-items for CommercialDocument; etc.) is the natural follow-up. Each concept promotion is one named test on real data, not a class hierarchy hand-built up-front. The `CanonicalConcept` enum still doesn't include SalesOrder / SalesOrderLine / ProductOffering / FulfillmentFlow / InventoryMovement / ProjectWorkItem / BillableWorkEntry — those land when ≥2-curator evidence appears (operator smoke target B needs a Spree harvest; smoke target C needs Project::TimeEntry + materialization rules). + +**Cross-repo alignment with `AdaWorldAPI/OGAR#61` + `#62`.** The merged `OGAR#61` introduced the `const CODEBOOK: &[(&str, u16)]` registry minting stable `u16` ClassIds for promoted canonical concepts (`project` `0x0001`, `project_work_item` `0x0002`, `billable_work_entry` `0x0003`). The merged `OGAR#62` (same day) added `("project_actor", 0x0004)` — collapsing the Redmine+OpenProject `User`/`Principal`/`ApplicationRecord` STI chain (4 source classes → one canonical) and proving binary cross-curator convergence on real Rails sources. The ar_shape `CanonicalConcept` enum is the UPSTREAM candidate set — concepts get promoted into OGAR's CODEBOOK once they've cleared the ≥2-curator gate AND the OGAR-side review. Each of this commit's `CanonicalConcept::{CommercialLineItem, CommercialDocument, TaxPolicy, BillingParty, PaymentRecord, CurrencyPolicy}` is a candidate row for a future OGAR CODEBOOK assignment (commerce / billing / erp domain, complementary to OGAR's existing project-management quartet). The STI-collapse pattern OGAR#62 demonstrated for `ProjectActor` is the same shape my `BillingParty` lexical detector applies on OSB::Client + Odoo::res_partner — same mechanism, different domain. + +**Cross-refs:** `crates/lance-graph-ontology/src/ar_shape.rs` (5 new detectors + `declared_classes` helper + 5 new tests; 19/19 green); `E-OGAR-AR-SHAPE-SMOKE-3` (OGIT canonical predecessor); `E-OGAR-AR-SHAPE-SMOKE-2` (predicate-vocabulary divergence finding); `E-OGAR-AR-SHAPE-SMOKE-1` (hand-fixture predecessor); `AdaWorldAPI/OGAR#61` (the upstream u16 CODEBOOK registry; each ar_shape canonical concept is a candidate for promotion into it). + +--- + +## 2026-06-19 — E-OGAR-AR-SHAPE-SMOKE-3 — OGIT is the canonical predicate vocabulary; OGAR consumes canonical via per-extractor codebooks; `translate_rails_to_ogit` + `translate_odoo_to_ogit` fold curator vocabularies into `ogit:includes/isMemberOf/contains/isPartOf` + +**Status:** FINDING (operator-directed clarification, 2026-06-19; 14/14 ar_shape tests green including 4 new OGIT-canonical ones). **Closes the predicate-vocabulary divergence from `E-OGAR-AR-SHAPE-SMOKE-2`** by naming what the convergence target IS, not just describing the divergence. + +**The click (operator-stated):** *"if we have one canonical, it just needs a codebook for import. and OGAR can use canonical."* + +**What this entry locks:** + +1. **OGIT defines the canonical predicate vocabulary.** Verified by reading `OGIT/SGO/sgo/verbs/{includes,isMemberOf,contains,isPartOf}.ttl` locally at `/home/user/OGIT/`. Each is a `owl:ObjectProperty` `subPropertyOf ogit:Verb`, defined by the AdaWorldAPI/OGIT canonical TTL: `ogit:includes` ("Indicates if an entity includes something else"), `ogit:isMemberOf` ("An entity can be a member of another entity"), `ogit:contains` ("This relationship indicates that something is part of something else"), `ogit:isPartOf` ("Indicates if an entity is part of another entity"). 176 OGIT verbs total in `SGO/sgo/verbs/`. Workspace usage already aligns: `lance-graph-ontology` is documented as *"the OGIT-canonical ontology spine"* (per `.claude/knowledge/ontology-registry.md`), and policy evaluation runs against *"canonical OGIT entity type"* (per the sprint-6 conformance test). + +2. **OGIT vs OGAR distinction (operator-confirmed):** OGIT = the canonical predicate vocabulary (source of `ogit:` IRIs in TTL). OGAR = the AR-shaped THINK/DO compiler that USES OGIT canonical (per `docs/OGAR_AR_SHAPE_ENDGAME.md`). Predicates stay `ogit:`-prefixed because OGIT TTL is their source; OGAR consumes them. There is no `ogar:` predicate prefix, only an OGAR consumer of `ogit:` predicates. `pub mod ogit_relations` in `ar_shape.rs` is correctly named. + +3. **Per-extractor codebooks fold curator vocab → OGIT canonical.** New `pub fn translate_rails_to_ogit(triples) -> Vec`: joins `declares_association` + `association_kind` and emits the directional OGIT predicate (`belongs_to → ogit:isMemberOf`, `has_many|has_one → ogit:includes`, `habtm → ogit:contains`). New `pub fn translate_odoo_to_ogit(triples, ns) -> Vec`: maps `target` → `ogit:isMemberOf` (conservative Many2one default; future Odoo-extractor extension can emit a sibling `field_kind` triple to dispatch on M2O / O2M / M2M). The codebook pattern dissolves `E-OGAR-AR-SHAPE-SMOKE-2`'s vocabulary-divergence finding: each extractor stays free to emit its native shape; OGAR consumes the canonical after a small per-extractor translation. + +4. **`classes_matching_commercial_line_item_shape_canonical` runs on OGIT-canonical triples directly.** Direction-blind: both `ogit:isMemberOf` (child→parent) and `ogit:includes` (parent→children) count as "relation present" for the doc-parent + tax-binding intersection. One detector, one canonical vocabulary, both curators surface their expected class on the real corpora: `InvoiceLineItem` on OSB (translated from `declares_association` + `association_kind`), `account_move_line` on Odoo (translated from `target`). + +**The collapse from the SMOKE-2 finding.** Before: two extractor jargons (`declares_association` for Rails, `target` for Odoo), one detector that had to dispatch on which predicate appeared. After: one OGIT-canonical vocabulary, one detector. Adding a new extractor (Spree, future SAP) means adding ONE codebook function; the detector stays unchanged. + +**What this means for the broader plan.** §11.1 Inc 4 (curator promotion probe): the codebook layer is the in-repo workaround that makes F4 falsifiable today on the existing corpus pair, NOT contingent on `E-AR-PROJECTION-CORRECTION-1` Phase 1 Option A (upstream alignment of nexgen's projection to emit unified Rails vocab). Both paths converge — upstream alignment can ship later as it's just moving the codebook one layer up. The doctrine §2 correction 4 (*"the ontology shapes everything agnostically through the contract"*) now has a concrete cash-out: the contract `Triple` carries OGIT-canonical predicates; the ontology (lance-graph-ontology) holds the codebook; consumers (OGAR detectors, future adapter codegen) read OGIT canonical and don't know which extractor produced it. + +**Out of scope (operator discipline acceptance #4-7):** still only one `CanonicalConcept` (`CommercialLineItem`). The OGIT-canonical detector is a TRANSPARENT replacement of the per-vocabulary one for that single concept; adding TaxPolicy / CommercialDocument / etc. is sibling functions, each gated by its own ≥2-curator harvest evidence. + +**Cross-refs:** `crates/lance-graph-ontology/src/ar_shape.rs` (`pub mod ogit_relations` + `translate_rails_to_ogit` + `translate_odoo_to_ogit` + `classes_matching_commercial_line_item_shape_canonical` + 4 new tests); `OGIT/SGO/sgo/verbs/{includes,isMemberOf,contains,isPartOf}.ttl` (the canonical predicate definitions); `E-OGAR-AR-SHAPE-SMOKE-2` (the predicate-vocabulary divergence finding this closes); `E-OGAR-AR-SHAPE-SMOKE-1` (the hand-fixture predecessor, retained); `.claude/knowledge/ontology-registry.md` (the "OGIT-canonical ontology spine" framing this entry implements). + +--- + +## 2026-06-19 — E-OGAR-AR-SHAPE-SMOKE-2 — operator pivot: ruff_ruby_spo replaces hand-fixtures, surfaces extractor-vocabulary divergence (Rails `declares_association` ≠ Odoo `target`); detector now vocabulary-aware on real 1195+ triple OSB + 2.8 MB Odoo corpora + +**Status:** FINDING (operator-directed pivot, 2026-06-19; 10/10 ar_shape tests green including 4 new harvest-driven ones). **The findings:** + +1. **ruff_ruby_spo built and ran clean against OSB** — `/tmp/sources/AdaWorldAPI-ruff-4c76178` + `AdaWorldAPI/open-source-billing@61cd6ed` → `cargo build -p ruff_ruby_spo --example harvest_op` (11.6 s, dev profile) → `OP_SRC= cargo run` → 43 models, 1195 triples, 121 KB ndjson. The Ruby/Rails extractor that openproject-nexgen-rs already uses works on OSB out of the box; checked in as `crates/lance-graph-ontology/tests/fixtures/osb_ruby_spo.ndjson`. + +2. **Known artefact (operator's "one tiny regex" point made literal):** `ruff_ruby_spo::NAMESPACE` is a `pub const &str = "openproject"`, so the OSB harvest is currently prefixed `openproject:` despite being OSB content. Fixable by a small upstream PR adding a parameterised `extract_with(path, ns)` to ruff_ruby_spo; the in-repo detector takes the prefix as an argument so the test stays correct. + +3. **Predicate-vocabulary divergence between the two extractors (the new structural finding):** the workspace's Odoo ndjson at `crates/lance-graph/src/graph/spo/odoo_ontology.spo.ndjson` has **0** `declares_association` triples — Odoo uses a different vocabulary entirely (`target`, `inverse_name`, `reads_field`, `traverses_relation`, `depends_on`, `emitted_by`, `validation_kind`, `has_function`, `inherits_from`, `raises`, `rdf:type`). Ruff's Ruby/Rails emitter uses `declares_association`, `association_kind`, `has_attribute`, `has_callback`, `acts_as`, `has_function`, `validates_constraint`, `validation_kind`, `validation_param`, `rdf:type`. They describe the same AR-shape primitives (associations between classes) under different predicate names. **This is the predicate-vocabulary analogue of the namespace-prefix divergence.** The §11.1 Inc 4 curator-promotion probe needs either (a) a small predicate-translation layer in the detector, or (b) upstream alignment per `E-AR-PROJECTION-CORRECTION-1` Phase 1 Option A (Odoo arms in openproject-nexgen's projection emitting the unified Rails vocabulary). + +4. **Path (a) shipped today as the in-repo workaround.** New `classes_matching_commercial_line_item_shape(triples, namespace_prefix)` walks BOTH predicate shapes — Rails `declares_association` (subject = class IRI, object = field-IRI carrying assoc leaf) AND Odoo `target` (subject = `.`, object = comodel name carrying signal). One detector, two extractor vocabularies. Plus minimal hand-rolled ndjson loader (zero-dep, handles `\"` escapes in `validation_param` rows that initially broke my naïve parser). + +5. **Result on real corpora:** OSB harvest surfaces `InvoiceLineItem` (via `declares_association tax1/tax2` + `invoice`). Odoo corpus surfaces `account_move_line` (via `target` `tax_ids → account.tax` + `move_id → account.move`). Both via the SAME detector, different code paths internally. `hand_fixture_and_corpus_detection_agree_on_invoice_line_item_pair` test pins it: hand fixtures from `E-OGAR-AR-SHAPE-SMOKE-1` and the harvest-driven detector AGREE on the pair, end-to-end. + +**What this means for the broader plan.** The §2 doctrine corrections still hold but get sharpened: +- §2 correction 1 *"curator distinction is one regex"* — TRUE for the namespace; **PARTIALLY-MISLEADING for the predicate vocabulary.** Two regexes (or one predicate-translation table) at minimum. +- §2 correction 2 *"synergy wiring is the work"* — IS WHAT JUST HAPPENED. The synergy detector is real code, not doctrine. +- §11.1 Inc 4 *"curator promotion probe"* — should ABSORB this predicate-vocab finding: F4 is unfalsifiable on today's corpus pair UNTIL either upstream-alignment (Phase 1 Option A) OR the translation layer (this entry) is the explicit dependency. Path (a) is now shipped → Inc 4 can proceed using vocabulary-aware detectors. + +**Out of scope (per operator discipline acceptance #4-7):** still only one `CanonicalConcept` (`CommercialLineItem`). TaxPolicy / CommercialDocument / BillingParty / PaymentRecord / CurrencyPolicy each get their own sibling detector + harvest-driven test before the enum extends. + +**Cross-refs:** `crates/lance-graph-ontology/src/ar_shape.rs` (the vocabulary-aware detector + ndjson loader + 4 new tests); `crates/lance-graph-ontology/tests/fixtures/osb_ruby_spo.ndjson` (1195 OSB triples harvested via ruff_ruby_spo, 119 KB); `crates/lance-graph/src/graph/spo/odoo_ontology.spo.ndjson` (existing 2.8 MB Odoo manifest, unchanged); `E-OGAR-AR-SHAPE-SMOKE-1` (the hand-fixture predecessor, retained); `AdaWorldAPI/ruff#26` (the Ruby class-reopen merge fix that makes Rails corpus surveys reopen-aware); `E-AR-PROJECTION-CORRECTION-1` (Phase 1 Option A as the upstream-alignment alternative). + +--- + +## 2026-06-19 — E-OGAR-AR-SHAPE-SMOKE-1 — first concrete synergy: OSB::InvoiceLineItem + Odoo::account.move.line → CanonicalConcept::CommercialLineItem (the ≥2-curator promotion rule mechanized; ar_shape lands in lance-graph-ontology) + +**Status:** FINDING (smoke-pass per operator directive 2026-06-19; the first concrete instance of the synergy-registry framing from `docs/OGAR_AR_SHAPE_ENDGAME.md` §2 corrections). The ≥2-curator promotion rule is no longer doctrine on paper — it's typed Rust code with 6 green tests. + +**What landed (one-PR-equivalent commit on the doctrine branch):** `crates/lance-graph-ontology/src/ar_shape.rs` — a self-contained ~310 LOC module carrying the minimal surface the operator's smoke-pass spec named: `SourceDomain { Billing, Erp, Commerce, Project }`, `SourceCurator { OpenSourceBilling, Odoo, Spree, Solidus, Redmine, OpenProject }`, `CanonicalConcept { CommercialLineItem }` (one variant only, per acceptance #4 minimal), `Class` fixture with `curator_label`/`shape`/`inherits`, `ClassShape::LineItem(LineItemShape)`, two hand-built fixtures `osb_invoice_line_item()` + `odoo_account_move_line()` (sourced from `AdaWorldAPI/open-source-billing@61cd6ed` `app/models/invoice_line_item.rb` + Odoo `account.move.line` already grounded in `odoo_blueprint::structural`), and `overlap_commercial_line_item(a, b) -> Option` enforcing the ≥2-curator promotion rule structurally (same-curator self-compare returns `None`; cross-curator with both shapes complete returns `Some(CommercialLineItem)`; symmetric; idempotent). `pub mod ar_shape` wired into `crates/lance-graph-ontology/src/lib.rs`. 6 tests green (`open_source_billing_invoice_line_and_odoo_move_line_overlap_as_commercial_line_item`, `rails_billing_and_odoo_do_not_create_duplicate_canonical_concepts`, `same_curator_self_compare_does_not_promote`, `curator_field_names_diverge_but_shape_still_promotes`, `namespace_prefixes_for_today_curators_are_stable`, `empty_tax_refs_block_promotion`). + +**Why this matters (doctrine→code).** Three §2 corrections from yesterday named what should now be true; this entry shows it IS true in code: +- §2 correction 1 *"curator distinction is one regex"* → `SourceCurator::namespace_prefix() -> &'static str` per curator. `open_source_billing:` and `odoo:` are now typed namespace prefixes carried on the fixture, exactly the regex distinction the correction named. +- §2 correction 2 *"synergy wiring is the work"* → `overlap_commercial_line_item` IS the synergy detector. It encodes the input synergy direction (multiple namespace-tagged classes resolve INTO one `CanonicalConcept`); the test pair `(OSB::InvoiceLineItem, Odoo::account.move.line) → CommercialLineItem` is the first row of the synergy registry. +- §2 correction 4 *"labels are leaf detail; ontology shapes through contract"* → curator labels (`item_unit_cost`, `price_unit`, `tax_1`, `tax_ids`, `item_quantity`, `quantity`, `item_description`, `name`) are `&'static str` on the fixture's `LineItemShape`; the canonical concept knows none of them; the ontology lives in `lance-graph-ontology` (correct home) and routes through the trait surface in `lance-graph-contract` (zero-dep, untouched). `curator_field_names_diverge_but_shape_still_promotes` is the test that pins it: divergent field names, same shape, same promotion. The labels are visible to the (future) adapter generator; the canonical concept is curator-blind. + +**Where future curators plug in.** Adding Spree / Solidus / Redmine / OpenProject / future SAP is mechanical: (1) new `SourceCurator` variant + `namespace_prefix`; (2) new fixture function `spree_line_item()` etc.; (3) the same `overlap_commercial_line_item` reuses against any pair across curators. Adding Tax / Document / Payment / SalesOrder concepts: new `CanonicalConcept` variant + new `ClassShape::TaxRate` / `Document` / etc. variant + sibling `overlap_*` function. No churn to existing types; pure addition. **The `Class` fixture is small and extends linearly.** + +**What this entry does NOT promote.** Per operator acceptance #4-7: only `CommercialLineItem` lands (one canonical concept). The other named concepts (`CommercialDocument`, `TaxPolicy`, `PaymentRecord`, `BillingParty`, `CurrencyPolicy`, `SalesOrder`, `SalesOrderLine`, `ProductOffering`, `FulfillmentFlow`, `InventoryMovement`, `ProjectWorkItem`, `BillableWorkEntry`) are deliberately deferred until ≥2-curator overlap is empirically demonstrated for each — same gate, applied once per concept. The TimeEntry → BillableWorkEntry → CommercialLineItem materialization-hinge ride (operator smoke target C) is the natural next concept once the Rails-side OSB project_task.rb / invoice_task.rb surface is paired against Odoo's analytic line. + +**Side note — disk + branch state.** The operator's "clean build residue across all branches" request freed 23.9 GB (3.9 GB → 27 GB free) by `cargo clean` on lance-graph's debug target. The branch is `claude/hydrate-dolce-dul-owl-Ce9Oa`, rebased on top of PR #547 (the same-day doctrine drift cleanup); 6/6 ar_shape tests green post-rebase. The 12 clippy errors visible at `cargo clippy -p lance-graph-ontology --lib --tests -- -D warnings` are PRE-EXISTING in `ttl_parse.rs` / `class_resolver.rs` (tracked workspace debt `TD-ONTOLOGY-LINT`); `ar_shape.rs` is clippy-clean. **No code change to `lance-graph-contract`; no new ENVELOPE_LAYOUT_VERSION; no `OgarAst` / `ThinkVerdict` / `Executor` yet** — those are the per-Inc work from `.claude/plans/ogar-ar-shape-endgame-v1.md` §11.1, separate PRs. + +**Cross-refs:** `crates/lance-graph-ontology/src/ar_shape.rs` (the module + 6 tests); `docs/OGAR_AR_SHAPE_ENDGAME.md` §2 corrections 1-4 (the doctrine this implements); `.claude/plans/ogar-ar-shape-endgame-v1.md` §1 Inc 4 (curator promotion table — the next concept extension lands here); `E-AR-PROJECTION-CORRECTION-1` (the bound on the SurrealQL adapter target — this entry is a pure ontology addition, independent of the Phase 1/2 placement); `E-OGAR-AR-SHAPE-ENDGAME` (the doctrine anchor); `AdaWorldAPI/open-source-billing@61cd6ed`; `AdaWorldAPI/ruff#26` (the upstream Ruby extractor fix that makes reopen-aware corpus surveying possible). --- diff --git a/.claude/board/INTEGRATION_PLANS.md b/.claude/board/INTEGRATION_PLANS.md index edb6f12b..d572ff71 100644 --- a/.claude/board/INTEGRATION_PLANS.md +++ b/.claude/board/INTEGRATION_PLANS.md @@ -1,6 +1,6 @@ ## 2026-06-19 — ogar-ar-shape-endgame-v1 (the ontology compiler — curators teach, OGAR metabolizes, AST/ARM/DLL routes, ractor-Lance-SurrealDB-callcenter execute) -**Status:** DOCTRINE-RATIFIED + PLAN-RATIFIED-with-required-remediations (5+3 council 2026-06-19 in plan §11). **Doctrine file:** `docs/OGAR_AR_SHAPE_ENDGAME.md` (operator-ratified, untouched by council). **Plan file:** `.claude/plans/ogar-ar-shape-endgame-v1.md` (5 Inc gates F1-F5 + Inc 3 SPLIT into 3a+3b + Inc 4 WEAKEN-or-DEFER + Inc 5 SPLIT into F5-smoke + F5-real). **PR:** #546. **Epiphany anchor:** `E-OGAR-AR-SHAPE-ENDGAME` (TOP of EPIPHANIES.md, dated 2026-06-19). +**Status:** **MERGED 2026-06-19 (PR #546, commit `7501a27`).** DOCTRINE-RATIFIED + PLAN-RATIFIED-with-required-remediations (5+3 council 2026-06-19 in plan §11). **Doctrine file:** `docs/OGAR_AR_SHAPE_ENDGAME.md` (operator-ratified, untouched by council). **Plan file:** `.claude/plans/ogar-ar-shape-endgame-v1.md` (5 Inc gates F1-F5 + Inc 3 SPLIT into 3a+3b + Inc 4 WEAKEN-or-DEFER + Inc 5 SPLIT into F5-smoke + F5-real). **Epiphany anchor:** `E-OGAR-AR-SHAPE-ENDGAME` (TOP of EPIPHANIES.md, dated 2026-06-19). **Council verdict (2026-06-19):** Architecturally sound; implementation specs ship with 2 P0 type-collisions + 1 P0 zero-dep breach + 1 BLOCKED gate (F4) + 1 fundamental design gap (F5 stubs-validating-stubs) — all remediable. Required remediations folded into plan §11.1: rename `Verdict` → `ThinkVerdict` (avoid `mul::GateDecision` collision); `ActionState` non_exhaustive + drop Copy/repr(u8); rename `OrchestrationBridge::route` overload to `route_ogar` + default impl; drop `Executor::ExternalHttp(Url)` (P0 zero-dep) + `Executor::Dll(CapabilityId)` (AP6 phantom); move `Executor::OdooAdapter`/`RailsAdapter` to callcenter trait (membrane integrity); split Inc 3 into 3a (contract) + 3b (planner stubs); WEAKEN F4 OR DEFER until E-AR-PROJECTION-CORRECTION-1 Phase 1 lands Odoo arms; split F5 into F5-smoke (stubs, lands now) + F5-real (one real executor pair, gates doctrine §10 promotion). **The spine (one line):** _Curators teach. OGAR compiles. LanceGraph thinks. SurrealAST + Kanban orchestrate. Adapters obey._ **The litmus failure name:** _"the curator wearing the crown"_ — same `OgarAst::Do(…)` MUST execute semantically identically across NativeLance / SurrealAST / Odoo adapter / Rails adapter; one backend leaking its syntax into the semantic result IS the bug. diff --git a/.claude/board/LATEST_STATE.md b/.claude/board/LATEST_STATE.md index d2c7f540..297cbd49 100644 --- a/.claude/board/LATEST_STATE.md +++ b/.claude/board/LATEST_STATE.md @@ -2,7 +2,7 @@ > **Auto-injected at session start via SessionStart hook.** > Updated after every merged PR. -> **Last updated:** 2026-05-14 (PR #372 merged: sprint-10 spec sprint, 12-worker CCA2A fleet + Opus meta-review + 8 knowledge docs, governance-only (zero .rs changes), mirrors PR #365 pattern. Sprint-11 implementation wave gated on 5 spec patches + 4 user ratifications: CSI-1 CausalEdge64 bit-reclaim Option, OQ-1 Σ4-Σ5 banding, OQ-3 plasticity granularity, OQ-5 rayon vendor. **Major findings:** (1) dual `CausalEdge64` types in workspace — `causal_edge::CausalEdge64` SPO-palette layout ≠ `thinking_engine::layered::CausalEdge64` 8-channel cascade, same name different semantics, surfaced as duplication entry #13 in TYPE_DUPLICATION_MAP and E-META-7 in EPIPHANIES; (2) p64 drift origin pinpointed at `crates/lance-graph-planner/src/cache/convergence.rs:18-22 #[allow(unused_imports)]` annotation — wiring intended for hot-path convergence never finished; (3) three-zone hot-path mental model corrects prior framing — Zone-1 thinking-engine MatVec 200-500ns + AriGraph entity_index O(1) ~20-200ns is the actual cycle-speed path, not DataFusion. Prior: 2026-05-13 (PR #366 merged: sprint-7 7-worker implementation wave for the sprint-5/6 specs + AuditSink trait unification, ~5 KLOC across 5 crates +2 new (`lance-graph-supervisor`, `lance-graph-consumer-conformance`), ~70 new tests, workspace clippy --tests --no-deps -D warnings exits 0; Opus meta verdict 4A/2B/1B-minus; OQ-7-1/2/3 all locked pre-merge; `UnifiedAuditSink` D-SDR-4 placeholder dropped, all sinks unified on `AuditSink` trait; `UnifiedBridge::with_jsonl_audit()` ergonomic constructor added for MedCare-rs sprint-2 item 5. **Adjacent landings (same day):** MedCare-rs sprint-1 10-PR sweep (#113-#122) including E1-1 OQ-3 direct migration (6 RoleGroups) consuming our `0d725d4` decision. MedCare-rs sprint-2 (5 PRs) is queued on user "go" — item 5 consumes this PR's new constructor. Prior same-day: PR #365 (13 sprint-5/6 specs + meta). Prior: PR #364 (D-SDR-3/4/5 + sprint-log-4 governance + sprint-5-9 roadmap + codex P1/P2 fixes). lance-graph #364 ships D-SDR-3/4/5 + sprint-log-4 governance + sprint-5-9 roadmap + codex P1/P2 surgical fixes (OwlIdentity 3-byte canonical, UnifiedAuditEvent 26 bytes, OgitFamilyTable sparse `HashMap`, audit super_domain via AuditChain). MedCare-rs#112 (PR-B) wires `UnifiedBridge` + medcare-rbac + medcare-realtime substrate (+2963 LOC, 17 files, §73 SGB V + BMV-Ä §57 + BtM regulatory tests). smb-office-rs#31 (PR-C) wires `UnifiedBridge` (+111 LOC). ndarray#142 ships VBMI gate for `permute_bytes` (P0 SIGILL fix on Skylake-X / Cascade Lake / Ice Lake-SP) + Inf clamp for `simd_exp_f32`. D-SDR-5 `UnifiedBridge` surface is now consumed end-to-end across MedCare + smb-office. Prior: 2026-05-07 (PR #354). Prior: 2026-05-07 (PR #353). Prior: 2026-05-07 (PR #352). Prior: 2026-05-06 (splat-osint-ingestion-v1 PR 1+2 of 6 in flight). Prior: 2026-04-21 post PR #243. +> **Last updated:** 2026-06-19 (PR #546 merged: OGAR AR-shape endgame doctrine + 5-Inc plan + 5+3 council verdict — DOCTRINE PR, ZERO code in `crates/*`. Closes the arc started by `E-AR-PROJECTION-CONVERGED` (third-curator finding on openproject-nexgen-rs) and bounded by `E-AR-PROJECTION-CORRECTION-1` (prior 5+3 retracting 2 sub-claims). Ships: `docs/OGAR_AR_SHAPE_ENDGAME.md` (~660 LOC, 13 sections + glossary, operator-ratified) + `.claude/plans/ogar-ar-shape-endgame-v1.md` (~430 LOC, 5-Inc ladder + 5+3 verdict in §11). **Doctrine locked:** _"Curators teach. OGAR compiles. LanceGraph thinks. SurrealAST + Kanban orchestrate. Adapters obey."_ + the litmus failure-name _"the curator wearing the crown"_ (same `OgarAst::Do` MUST execute semantically identically across NativeLance/SurrealAST/Odoo/Rails adapters; backend syntax leaking into semantic result IS the bug). **OGAR IS the AR-shaped THINK/DO compiler;** Foundry/Gotham/OpenProject/Odoo are schema+inheritance INPUTS, not external systems. **Curator promotion rule:** primitive enters OGAR Core ONLY when ≥2 independent curators surface it under different syntactic forms. **Ownership boundaries (corrected, operator-ratified):** ractor = compile-time mailbox-as-owner guarantee (NOT runtime mutation authority); LanceGraph = thinking plane; SurrealAST + Kanban = orchestration plane; OGAR = meaning; contract = interface promises; callcenter = outer membrane. **THING/DO/THINK triad invariant:** THING is read, DO writes (gated), THINK never writes. 5 Inc PRs deferred with §11.1 remediations: rename `Verdict`→`ThinkVerdict` (avoid `mul::GateDecision` collision); `ActionState` non_exhaustive + drop Copy/repr(u8); split Inc 3 into 3a (contract) + 3b (planner stubs); rename `OrchestrationBridge::route`→`route_ogar` with default impl; drop `Executor::ExternalHttp(Url)` (P0 zero-dep breach via `url` crate) + `Dll(CapabilityId)` (AP6 phantom); move named adapter variants to callcenter behind `ExecutorTarget` trait; WEAKEN F4 to ≥2-in-≥2 OR DEFER until E-AR-PROJECTION-CORRECTION-1 Phase 1 ships nexgen Odoo arms; split F5 into F5-smoke (lands now) + F5-real (gates doctrine §10 promotion). **Surprise win (cascade-impact):** `ActionState` has ZERO downstream consumers in workspace — Inc 1's `ThinkRejected` variant addition is free of cross-crate cascade. **The 5+3 council verdict (panel: convergence/prior-art/dto-soa/cascade-impact/core-first; critique: truth-architect/baton-handoff/iron-rule) is appended to plan §11.** Doctrine OPERATOR-RATIFIED + not subject to council; only implementation specs sharpened. 5 open questions §9 resolved decided. **The placement-question council (E-AR-PROJECTION-CORRECTION-1) stands** — Phase 1 Option A (Odoo arms in nexgen RFC) + Phase 2 Option D (surrealdb-fork C16b/C16c per `/home/user/surrealdb/.claude/op-codegen-bridge/README.md` ACTIVE initiative). It concerns the SurrealQL adapter target = ONE leg of the ARM layer, NOT the ontology. This doctrine is upstream of placement. Prior: 2026-05-14 (PR #372 merged: sprint-10 spec sprint, 12-worker CCA2A fleet + Opus meta-review + 8 knowledge docs, governance-only (zero .rs changes), mirrors PR #365 pattern. Sprint-11 implementation wave gated on 5 spec patches + 4 user ratifications: CSI-1 CausalEdge64 bit-reclaim Option, OQ-1 Σ4-Σ5 banding, OQ-3 plasticity granularity, OQ-5 rayon vendor. **Major findings:** (1) dual `CausalEdge64` types in workspace — `causal_edge::CausalEdge64` SPO-palette layout ≠ `thinking_engine::layered::CausalEdge64` 8-channel cascade, same name different semantics, surfaced as duplication entry #13 in TYPE_DUPLICATION_MAP and E-META-7 in EPIPHANIES; (2) p64 drift origin pinpointed at `crates/lance-graph-planner/src/cache/convergence.rs:18-22 #[allow(unused_imports)]` annotation — wiring intended for hot-path convergence never finished; (3) three-zone hot-path mental model corrects prior framing — Zone-1 thinking-engine MatVec 200-500ns + AriGraph entity_index O(1) ~20-200ns is the actual cycle-speed path, not DataFusion. Prior: 2026-05-13 (PR #366 merged: sprint-7 7-worker implementation wave for the sprint-5/6 specs + AuditSink trait unification, ~5 KLOC across 5 crates +2 new (`lance-graph-supervisor`, `lance-graph-consumer-conformance`), ~70 new tests, workspace clippy --tests --no-deps -D warnings exits 0; Opus meta verdict 4A/2B/1B-minus; OQ-7-1/2/3 all locked pre-merge; `UnifiedAuditSink` D-SDR-4 placeholder dropped, all sinks unified on `AuditSink` trait; `UnifiedBridge::with_jsonl_audit()` ergonomic constructor added for MedCare-rs sprint-2 item 5. **Adjacent landings (same day):** MedCare-rs sprint-1 10-PR sweep (#113-#122) including E1-1 OQ-3 direct migration (6 RoleGroups) consuming our `0d725d4` decision. MedCare-rs sprint-2 (5 PRs) is queued on user "go" — item 5 consumes this PR's new constructor. Prior same-day: PR #365 (13 sprint-5/6 specs + meta). Prior: PR #364 (D-SDR-3/4/5 + sprint-log-4 governance + sprint-5-9 roadmap + codex P1/P2 fixes). lance-graph #364 ships D-SDR-3/4/5 + sprint-log-4 governance + sprint-5-9 roadmap + codex P1/P2 surgical fixes (OwlIdentity 3-byte canonical, UnifiedAuditEvent 26 bytes, OgitFamilyTable sparse `HashMap`, audit super_domain via AuditChain). MedCare-rs#112 (PR-B) wires `UnifiedBridge` + medcare-rbac + medcare-realtime substrate (+2963 LOC, 17 files, §73 SGB V + BMV-Ä §57 + BtM regulatory tests). smb-office-rs#31 (PR-C) wires `UnifiedBridge` (+111 LOC). ndarray#142 ships VBMI gate for `permute_bytes` (P0 SIGILL fix on Skylake-X / Cascade Lake / Ice Lake-SP) + Inf clamp for `simd_exp_f32`. D-SDR-5 `UnifiedBridge` surface is now consumed end-to-end across MedCare + smb-office. Prior: 2026-05-07 (PR #354). Prior: 2026-05-07 (PR #353). Prior: 2026-05-07 (PR #352). Prior: 2026-05-06 (splat-osint-ingestion-v1 PR 1+2 of 6 in flight). Prior: 2026-04-21 post PR #243. > > Purpose: prevent new sessions from hallucinating structure that > already exists or proposing features already shipped. Read this @@ -11,6 +11,11 @@ --- > **2026-06-19 — IN PR (branch `claude/edge-distance-basin-node-epiphany`)** — **basin-IS-a-node: the substrate is a virtual tree of MailboxSoAs, navigated by pure key arithmetic.** New `graph::mailbox_scan::{members, memberof, BasinOf}` — one-to-many (`members` = direct children one HHTL tier down) / many-to-one (`memberof` = parent via `NiblePath::parent`, returns `BasinOf::Local(row)` or `BasinOf::Route(NiblePath)` when the parent lives in another shard — the HHTL prefix IS the route key, **no coarse-fingerprint table**; `None` only at the top tier). Realizes `E-BASIN-IS-A-NODE` with **no ownership restructure** — the tree is the radix trie of the keys, the SoA stays flat, the zero-copy/Lance-tombstone invariant is untouched; all navigation is **zero value decode** (F2-guarded). 16/16 mailbox_scan tests, clippy clean. **Probe (perturbation-sim `basin_placement_learning.rs`): field-perturbation placement learns the basin tree — green, mean tree-hop 1.00 vs 4.13 random (75.8 % tighter)**, promoting the one CONJECTURE in `E-BASIN-IS-A-NODE` to measured FINDING [G]. **Three epiphanies this arc:** `E-BASIN-IS-A-NODE` (basin=node; distance=hop=`node_distance(PrefixDepth)`; 4-ary fan-out = Morton tile pyramid = perturbation-learnable field), `E-FAMILY-NODE-IS-META-AWARENESS` (the parent node IS the coarse Walsh band of its subtree — meta-awareness is structural, not a column), `E-GUID-SELF-ROUTES-THE-BASIN-TREE` (HHTL-tier truncation of the GUID = every ancestor's route key; the GUID self-routes). **Capstone:** one 512 B key, read five ways — representation / ontology / compute (Morton pyramid) / learning / meta-awareness — four of the five are key-resident zero-decode. Builds on #544/#545/#548 (mailbox_scan facets) + `E-COARSE-QUANTIZER-IS-SCALE-FREE-ROUTER`. +> **2026-06-19 — branch work** — **First concrete synergy convergence: `ar_shape` module + `CommercialLineItem` canonical concept.** Smoke pass per operator directive 2026-06-19. New `crates/lance-graph-ontology/src/ar_shape.rs` (~310 LOC) carries `SourceDomain` (Billing/Erp/Commerce/Project), `SourceCurator` (OpenSourceBilling/Odoo/Spree/Solidus/Redmine/OpenProject + `namespace_prefix() -> &'static str`), `CanonicalConcept::CommercialLineItem` (one variant only — operator acceptance #4 "minimal canonical"), hand-built `Class` fixtures `osb_invoice_line_item()` (sourced from `AdaWorldAPI/open-source-billing@61cd6ed` `app/models/invoice_line_item.rb`) + `odoo_account_move_line()` (already grounded in `odoo_blueprint::structural`), `overlap_commercial_line_item(a, b) -> Option` enforcing the ≥2-curator promotion rule structurally. 6 green tests including the headline `open_source_billing_invoice_line_and_odoo_move_line_overlap_as_commercial_line_item` + `same_curator_self_compare_does_not_promote` (the promotion-rule structural guard) + `curator_field_names_diverge_but_shape_still_promotes` (the labels-are-leaf-detail proof). Mechanizes the §2 correction chain on the doctrine: namespace prefix IS curator distinction (correction 1); `overlap_*` IS the synergy detector (correction 2); curator field names live on the fixture, canonical concept is curator-blind (correction 4). Pure addition to `lance-graph-ontology`; no contract change, no new `OgarAst`/`ThinkVerdict`/`Executor` (those are §11.1 Inc PRs). `ar_shape.rs` itself clippy-clean; 12 pre-existing clippy errors in `ttl_parse.rs`/`class_resolver.rs` are tracked workspace debt (`TD-ONTOLOGY-LINT`). Also: operator request "clean build residue across all branches in your backend" — `cargo clean` on `lance-graph/target` freed 23.9 GB (3.9 GB → 27 GB free). Branch `claude/hydrate-dolce-dul-owl-Ce9Oa`, rebased on top of PR #547. EPIPHANIES `E-OGAR-AR-SHAPE-SMOKE-1`. ruff#26 (the upstream Ruby class-reopen merge fix) is the harvest-side counterpart enabling reopen-aware Rails corpus surveys. +> +> **2026-06-19 — MERGED #547** (docs cleanup of #546 doctrine drift): merge commit `5ad6871`, branch `claude/doctrine-drift-cleanup`. ~46 lines / 25+/-21 in `docs/OGAR_AR_SHAPE_ENDGAME.md`. Tightens `ractor compile-time owner` → `ractor-proven` in the §0 ladder; slims the `Executor` enum mention to match §11.1 Inc 3 remediation (`NativeLance / SurrealAst / HumanKanban / Adapter(&'static str)` only; `Url`/`Dll`/named-adapter variants moved out per the council). Doc-only; no code touched. +> +> **2026-06-19 — MERGED #546** (OGAR AR-shape endgame doctrine + 5-Inc plan + 5+3 council verdict): merge commit `7501a27`, branch `claude/hydrate-dolce-dul-owl-Ce9Oa`. ~1,090 LOC across 4 governance files; ZERO code in `crates/*`. Doctrine-only. Closes the arc that started with `E-AR-PROJECTION-CONVERGED` (third-curator finding on openproject-nexgen-rs) + was bounded by `E-AR-PROJECTION-CORRECTION-1` (prior 5+3 retracting 2 sub-claims, naming Phase 1 nexgen RFC + Phase 2 surrealdb-fork C16b/C16c as the typed-AST placement path). New artifacts: `docs/OGAR_AR_SHAPE_ENDGAME.md` (13 sections + glossary, operator-ratified — THING/DO/THINK trichotomy, AST/ARM/DLL operation grammar, curator promotion rule ≥2-in-≥2, ownership boundaries with the ractor compile-time correction, Invoice worked example) + `.claude/plans/ogar-ar-shape-endgame-v1.md` (5-Inc ladder with falsifying gates F1-F5; §11 full 5+3 council verdict). **The spine:** _Curators teach. OGAR compiles. LanceGraph thinks. SurrealAST + Kanban orchestrate. Adapters obey._ **Litmus failure-name:** _the curator wearing the crown_ — same `OgarAst::Do` MUST execute semantically identically across all executor backends. **Locked:** OGAR IS the AR-shaped THINK/DO compiler; Foundry/Gotham/OpenProject/Odoo are schema+inheritance INPUTS not external systems; ractor is compile-time mailbox-as-owner ONLY (not runtime mutation authority); LanceGraph = thinking plane; SurrealAST + Kanban = orchestration plane; callcenter = outer membrane. THING/DO/THINK triad invariant: THING read / DO writes gated / THINK never writes. **Deferred (5 Inc PRs with §11.1 remediations):** Inc 1 rename `Verdict`→`ThinkVerdict` + `ActionState` non_exhaustive + drop Copy/repr(u8); Inc 2 + `OgarAst::to_triples` canonical proof at F2; Inc 3 SPLIT into 3a (contract) + 3b (planner stubs); rename `OrchestrationBridge::route`→`route_ogar` with default impl; drop `Executor::ExternalHttp(Url)` (P0 zero-dep breach via `url` crate) + `Dll(CapabilityId)` (AP6 phantom); named adapter variants move to callcenter behind `ExecutorTarget` trait; Inc 4 WEAKEN F4 to ≥2-in-≥2 OR DEFER until nexgen Odoo arms ship; Inc 5 split into F5-smoke (lands now) + F5-real (gates doctrine §10 promotion via one real executor pair + property-fuzz on tz/decimal/collation/NULL). 5 open questions §9 resolved decided. **Surprise win (cascade-impact):** `ActionState` has ZERO downstream consumers in workspace — Inc 1's `ThinkRejected` variant addition is free of cross-crate cascade. Doctrine §10 stays CONJECTURE until F5-real runs green. Council corrections from this PR are recorded in plan §11 (panel 5 + critique 3 verdicts). E-AR-PROJECTION-CORRECTION-1 typed-AST placement path stands — concerns ONE leg of ARM (SurrealQL adapter target), not the ontology. > > **2026-06-18 — branch work** — **OGAR → lance-graph-ontology wiring closed.** `OntologyRegistry::class_id_for_guid(&NodeGuid) -> Option` composes the canon GUID→NiblePath fold (`contract::hhtl::NiblePath::from_guid_prefix`) with the registry's `NiblePath ↔ entity_type` bijection — the single missing join an audit this session surfaced (both halves were built with **ZERO callers**). A node carrying a classid now resolves its ontology class → `RegistryClassView` (fields/labels/template/DOLCE). Round-trip test pins the `classid_lo ↔ entity_type` consistency the audit flagged; zero-fallback (unbound → None) + lossy-fold refusal (high classid u16 → None). Completes the third "classid → X" axis reachable from a GUID (read-mode ✅ ocr.rs, methods ✅ unicharset keystone, ontology-shape ✅ now); aligns with `E-ODOO-CORE-FIRST-STRUCTURAL` (Core-side resolution, no new predicate/type). 16 ontology tests green; `registry.rs` clippy-clean + fmt clean. EPIPHANIES `E-OGAR-ONTOLOGY-WIRED-1`. Pre-existing `lance-graph-ontology` clippy debt noted (`TD-ONTOLOGY-LINT`). > diff --git a/.claude/board/PR_ARC_INVENTORY.md b/.claude/board/PR_ARC_INVENTORY.md index 06aa4e5d..4228a9dd 100644 --- a/.claude/board/PR_ARC_INVENTORY.md +++ b/.claude/board/PR_ARC_INVENTORY.md @@ -46,6 +46,17 @@ **Deferred:** the full online iterative placement learner (inject delta → minimise cascade surprise → re-place); `memberof` cross-shard row-fetch via a path→row index (today the route key is returned, the fetch is the consumer's); CHAODA as unary `node_anomaly` (reclassified out of `DistanceMeans`); helix/PqAdc value-tier means. **Confidence (2026-06-19):** navigation + probe green locally; zero-decode F2 guard tested; awaiting PR review. +## #546 OGAR AR-shape endgame doctrine + 5-Inc plan + 5+3 council verdict + +**Status:** MERGED 2026-06-19 (merge commit `7501a27`), branch `claude/hydrate-dolce-dul-owl-Ce9Oa`. **+1,090 LOC across 4 governance files; ZERO code in `crates/*`.** Doctrine-only PR that closes the arc started by `E-AR-PROJECTION-CONVERGED` (the third-curator finding on openproject-nexgen-rs) and was bounded by `E-AR-PROJECTION-CORRECTION-1` (the prior 5+3 council retracting two sub-claims). + +- **Added** — `docs/OGAR_AR_SHAPE_ENDGAME.md` (13 sections + glossary, ~660 LOC; the doctrine: OGAR-is-the-compiler, THING/DO/THINK, AST/ARM/DLL, curator promotion rule, ractor compile-time / LanceGraph thinks / SurrealAST+Kanban orchestrate ownership boundaries, Invoice worked example, CONJECTURE/FINDING ledger §12). `.claude/plans/ogar-ar-shape-endgame-v1.md` (~430 LOC, the 5-Inc implementation plan with falsifying gates F1-F5 + §11 5+3 council verdict). `EPIPHANIES.md` PREPEND `E-AR-PROJECTION-CONVERGED` (third-curator finding) + `E-AR-PROJECTION-CORRECTION-1` (5+3 council retractions) + `E-OGAR-AR-SHAPE-ENDGAME` (the doctrine anchor with spine + litmus phrases). `INTEGRATION_PLANS.md` PREPEND `ogar-ar-shape-endgame-v1`. +- **Locked** — **The spine (memorize, one line):** _Curators teach. OGAR compiles. LanceGraph thinks. SurrealAST + Kanban orchestrate. Adapters obey._ **The litmus failure name:** _the curator wearing the crown_ — same `OgarAst::Do(PostInvoice, …)` MUST execute semantically identically across NativeLance / SurrealAST / Odoo adapter / Rails adapter; one backend leaking syntax into semantic result IS the bug. **OGAR is the AR-shaped THINK/DO compiler;** Foundry/Gotham/OpenProject/Odoo are schema+inheritance INPUTS, not external systems OGAR adapts to. **Curator promotion rule:** a primitive enters OGAR Core ONLY when ≥2 independent curators surface it under different syntactic forms. **Ownership boundaries (operator-ratified, ractor correction included):** ractor = compile-time mailbox-as-owner guarantee (NOT runtime mutation authority — UB becomes a compile error per canonical §9 E-CE64-MB-4); LanceGraph = thinking plane (MailboxSoA + compute_dag + cycle-aware writes); SurrealAST + Kanban = orchestration plane; OGAR = meaning; contract = interface promises; callcenter = outer membrane. **THING is read. DO writes (gated). THINK never writes** — triad invariant. +- **Deferred** — All 5 Incs: PLAN-RATIFIED with required remediations per §11.1. **Inc 1** (`ClassView::policies` + `ThinkVerdict` rename from `Verdict` to avoid `mul::GateDecision` collision + `ActionState` non_exhaustive). **Inc 2** (`OgarAst` + `TripletProjection` round-trip; canonical Triple emitter proof at F2). **Inc 3** SPLIT into 3a (contract: `ArmDecision` + slim `Executor` enum + `route_ogar` with default impl) + 3b (planner stubs; SurrealAst declares cross-plan dep on `cypher-kanban-ast-unification-v1` Inc 1). **Inc 4** RATIFIED-conditional (operator picks: WEAKEN F4 to ≥2-in-≥2, OR DEFER until `E-AR-PROJECTION-CORRECTION-1` Phase 1 ships Odoo arms in nexgen). **Inc 5** split into F5-smoke (stubs lands now) + F5-real (one real executor pair gates doctrine §10 promotion). Doctrine §10 stays CONJECTURE until F5-real runs green. **Dropped from Inc 3:** `Executor::ExternalHttp(Url)` (P0 zero-dep contract breach — `url` crate), `Executor::Dll(CapabilityId)` (AP6 phantom — `CapabilityId` undefined), named `Executor::OdooAdapter`/`RailsAdapter` (move to callcenter behind `ExecutorTarget` trait; contract holds only `Executor::Adapter(&'static str)` discriminator — membrane integrity per doctrine §9). **Optional collapse:** Inc 1 + `probe-excel-compute-dag-v1` Inc 0 are the same `ClassView` evolution (convergence-architect recommends ship as ONE PR; not required). +- **Council (5+3, 2026-06-19)** — Panel: convergence-architect / prior-art-savant / dto-soa-savant / cascade-impact-savant / core-first-architect. Critique: truth-architect / baton-handoff-auditor / iron-rule-savant. Doctrine OPERATOR-RATIFIED (not subject to council); only plan §11.1 names code-level remediations. 5 open questions §9 resolved (decided, not deferred): Q1 `ClassView::policies` (mirror `compute_dag` precedent), Q2 `BindingSet = BTreeMap<&'static str, NodeGuid>` zero-dep, Q3 crown-format locked, Q4 reuse `/tmp/sources/AdaWorldAPI-openproject-nexgen-rs-bb957b0` (3.5 MB exists; no vendoring), Q5 ClassView extensions additive. **Surprise win (cascade-impact):** `ActionState` has ZERO downstream consumers in workspace — only `action.rs` itself; Inc 1's `ThinkRejected` variant addition is free of cross-crate cascade. +- **Bounds (carried)** — `E-AR-PROJECTION-CORRECTION-1` Phase 1 Option A (Odoo arms in nexgen) + Phase 2 Option D (surrealdb-fork C16b/C16c per `/home/user/surrealdb/.claude/op-codegen-bridge/README.md`) STAND. They concern the SurrealQL adapter target = ONE leg of the ARM layer, not the ontology itself. This PR is upstream of that placement question. +- **Docs** — `docs/OGAR_AR_SHAPE_ENDGAME.md`, `.claude/plans/ogar-ar-shape-endgame-v1.md`, `EPIPHANIES.md` (3 entries: `E-AR-PROJECTION-CONVERGED` + `E-AR-PROJECTION-CORRECTION-1` + `E-OGAR-AR-SHAPE-ENDGAME`), `INTEGRATION_PLANS.md`. +- **Confidence (2026-06-19):** working — doctrine + plan + council verdict merged; no code changed in this PR. The 5 Inc PRs ride per-Inc on the doctrine branch with §11.1 remediations folded in. --- diff --git a/docs/OGAR_AR_SHAPE_ENDGAME.md b/docs/OGAR_AR_SHAPE_ENDGAME.md index ab842f2b..9629334d 100644 --- a/docs/OGAR_AR_SHAPE_ENDGAME.md +++ b/docs/OGAR_AR_SHAPE_ENDGAME.md @@ -144,6 +144,156 @@ The doctrine: **the curator teaches by example. The ontology survives by being more abstract than any one curator.** A primitive is only Core-grade when ≥2 independent curators surface it under different syntactic forms. +### Correction (2026-06-19, operator) — the curator distinction is one regex + +The per-curator role list above (Rails / Odoo / WoA / SMB / SAP each with a +distinct "Role:" sentence) read this doc as if each curator demanded a +distinct architecture — that overstates the mechanical reality. **The +curator distinction at the harvest→AST seam is one tiny regex.** +OpenProject is a project-management domain; Odoo is an ERP domain. At the +extractor surface they emit the SAME AR-shape predicate vocabulary +(`rdf:type` / `has_attribute` / `declares_association` / …) on the SAME +`codegen_spine::Triple` carrier; they differ only in their namespace +prefix (`openproject:` vs `odoo:`). `from_triples::strip_namespace` needs +to recognise both (and any future ERP prefix); that's the entire +mechanical difference. Domain identity rides the namespace; the compiler +treats curators uniformly. + +The per-curator "Role:" sentences ABOVE still read accurately as +*what each curator teaches the ontology* (Odoo's regulatory anchors, WoA's +GoBD audit chain, OpenProject's project-management primitives, SMB-Office's +legacy German ERP behaviour). They do NOT mean the compiler architecture +varies by curator — the variation is the namespace, full stop. + +### Correction follow-on (2026-06-19, operator) — once domains are namespaced, the work is synergy wiring + +The regex correction above closes one question and opens the next: **what +DOES the compiler do, once the namespaces are distinguished?** Answer: +**wire synergies between namespace-tagged inputs and the OGAR Core**. +Synergies are bidirectional: + +- **Input synergy (curator promotion):** multiple namespace-prefixed + identities resolve INTO one OGAR class identity. The ≥2-curator + promotion rule is the resolver: + `{ odoo:account_move, openproject:invoice, woa:vorgang(doc_type=invoice), + sap:bkpf+bseg } → ogar:Invoice <: LegalDocument`. + Same shape for primitives that aren't classes but predicates / kinds: + `{ odoo:fields.Selection('state'), woa:WoStatusAction(enum), + openproject:status_id, rails:acts_as_state_machine } → ogar:StateMachine`. +- **Output synergy (adapter dispatch):** one OGAR class projects OUT to + multiple namespace-prefixed targets via the §3 `adapter_targets` slot + + the ARM `Executor::Adapter(&'static str)` discriminator (post §11 + remediations). `ogar:Invoice → { odoo:account_move, + rails:invoice_ar, woa:vorgang, sap:fi_document }`. + +**The synergy registry is the work.** Inc 4's "curator promotion table" +is exactly this registry mechanised — the §11.1 framing should read it +that way (synergy table, not just a promotion log). Each row of the +registry is a synergy: `(ogar_class, [namespace-tagged inputs], +[namespace-tagged outputs])`. Inc 4's F4 gate (≥4 primitives surface +under ≥2 curators) is the falsifier that the registry actually has +SYNERGIES, not just single-curator entries dressed up as "promoted." + +This sharpens §3 (the class shape `adapter_targets` is the output-synergy +slot — already named, just unlabelled as synergy), §11.1 Inc 4 (the +promotion table IS the synergy table), and §10's Invoice example (the +four `adapter_targets` listed there ARE the output synergies of +`ogar:Invoice`). + +### Correction punchline (2026-06-19, operator) — _"tadaa"_: WoA-rs consumes ERP through the synergy registry, not through SurrealQL + +The synergy framing above closes the loop with +`E-AR-PROJECTION-CORRECTION-1` (the 5+3 council that retracted the +"WoA-rs as first SurrealQL consumer" claim because WoA is sea-orm / +MySQL / axum, not SurrealDB). The retraction stands for **SurrealQL +specifically** — WoA never consumed the SurrealQL DDL adapter target, +and never will under its locked stack. What WoA-rs DOES consume — and +what makes it a first downstream consumer of the OGAR Core IN A WAY +THAT IS NOW MECHANICALLY CORRECT — is the **synergy registry**. + +The flow (with WoA on its native stack, no SurrealQL anywhere): + +``` + curators synergy registry consumer + ───────── ───────────────── ──────── + odoo:account_move ─┐ ┌─ woa:vorgang + openproject:invoice ─┼─► ogar:Invoice ─┼─► sea-orm Entity (MySQL) + sap:bkpf+bseg ─────┘ (cross-curator │ + (read into OGAR via promoted; carries └─ codegen against + namespace prefix + regulatory anchor + OGAR class shape + ≥2-curator rule) state machine + instead of + audit chain + hand-rolling + adapter_targets) per-curator) +``` + +WoA-rs's first cross-curator value isn't "render SurrealQL" — it's +**inherit the cross-curator definition of `Invoice` (Odoo's regulatory +GoBD anchors + OpenProject's PM linkage + future SAP's FI mapping) and +project it onto its own sea-orm/MySQL adapter target**. The SurrealQL +adapter target stays one of N output synergies (per `E-AR-PROJECTION- +CORRECTION-1` Phase 1/2 placement); sea-orm is another; both project +from the same `ogar:Invoice` class shape. + +This is the _tadaa_: once domains are namespaced (regex) and synergies +are wired (registry), every consumer — WoA-rs (sea-orm/MySQL), +smb-office-rs (MongoDB), future SAP NetWeaver, future SurrealQL — projects +from ONE OGAR class shape via its own `Executor::Adapter` target. No +consumer needs the SurrealQL adapter to benefit; SurrealQL is just one +of the projection lanes. WoA-rs becomes a first consumer of the +**synergy registry**, not the SurrealQL DDL — and that distinction is +what makes the "first downstream consumer" framing finally honest. + +### Correction (2026-06-19, operator) — labels are leaf detail; the ontology shapes everything agnostically through the contract + +The synergy-registry framing above leaves one more thing implicit. The +final crisp statement: **per-curator labels are a tiny detail in the +OGAR class-inheritance tree; the ontology does the shaping; the contract +routes it agnostically.** + +Per-curator labels — `odoo:account.move` as a model name, `move_type` / +`state` field names, German / English / French translation strings, the +specific view-XML or AR-attribute syntax a curator emits — are +**leaf-level decoration** that hangs off the OGAR class-inheritance +edge. They are NOT the architecture. The inheritance is the structure +(`Invoice <: LegalDocument <: EconomicCommitment <: SocialObject`); the +labels are what the curator named the leaf in its own namespace, and +they survive in the synergy registry only as `&'static str` adapter +target ids (`Executor::Adapter("odoo:account_move")`, etc.). + +What does the shaping is the ontology in `lance-graph-ontology`. It +shapes: + +- **The ERP** — what an `Invoice` MEANS (the regulatory anchor, the + state machine, the audit-chain requirement), independent of which + curator surfaced it first. +- **The classes** — the inheritance tree (THING), the action set (DO), + the policy set (THINK). +- **The adapters** — the `Executor::Adapter(namespace_id)` discriminator + per class, with each consumer registering its adapter behind the + callcenter `ExecutorTarget` trait (per §11.1 Inc 3 remediation). +- **The interfaces** — the trait shapes (`ClassView`, `ClassActions`, + `ClassMethods`, `policies`, `compute_dag`) consumers depend on to + consume an OGAR class. +- **The routes** — `ArmDecision::route_ogar(op, actor) → executor` via + `OrchestrationBridge`, with the ontology deciding which executor + handles which class-instance-action for which actor. + +**All of this routes AGNOSTICALLY through the `lance-graph-contract` +crate** — which is zero-dep, trait-only, and the workspace's +P0-invariant substrate (per CLAUDE.md § Workspace Structure: "ZERO +DEPS"). The contract carries the trait surfaces (`OrchestrationBridge`, +`ClassView`, `Executor`, `Triple`, `OgarAst`); the ontology fills them +with per-class shape; the consumers read the shape and project it onto +their native adapter. The contract never knows whether the consumer is +WoA's sea-orm or SMB's MongoDB or SurrealQL's DDL; the ontology never +knows either. Both layers are curator-agnostic by construction. + +The _tadaa_ again, rotated: **once the labels become leaf detail and the +ontology does the shaping, every consumer — present and future — just +plugs in through the contract. The ontology grows by adding classes / +synergies / policies; consumers grow by adding adapters. Nothing else +changes.** + --- ## 3. OGAR inherited class model