|
| 1 | +# odoo-business-logic-blueprint-v1 — typed Odoo entity DTOs as the substrate for the OGIT → OWL → DOLCE → FIBU/FIBO normalization + JITson / recipe codegen |
| 2 | + |
| 3 | +> **Status:** PROPOSAL. **PREREQUISITE for `odoo-savant-reasoners-v2` Group F** |
| 4 | +> (per `E-SAVANT-COMPOSITION-1`): v2's `SavantPattern` consts compose *over |
| 5 | +> normalized typed DTOs*; without this blueprint they would be ad-hoc |
| 6 | +> interpretations of L-doc prose. This plan establishes the missing layer |
| 7 | +> between Odoo prose curation and the agnostic shader substrate. |
| 8 | +> |
| 9 | +> **Confidence:** HIGH on the structure (typed DTOs are the missing inheritance-chain |
| 10 | +> input; today every OGIT/OWL/DOLCE/FIBU layer string-keys against `model_name`). |
| 11 | +> MED on per-lane density sizing (15 lanes × ~5-30 entities each = ~150-450 |
| 12 | +> const declarations is an estimate; actual count depends on lane density). |
| 13 | +> HIGH on the JITson wiring path (the infrastructure exists at |
| 14 | +> `lance-graph-contract::jit` + `thinking-engine` Cranelift integration — |
| 15 | +> just not yet pointed at recipes/savants). |
| 16 | +> |
| 17 | +> **Predecessors:** PR #411 (33-TSV atoms + 34 `Tactic` kernels + `jit` |
| 18 | +> infrastructure), PR #412 (DOLCE classifier + `dolce_odoo`), PR #414 |
| 19 | +> (`D-ODOO-SAV-1/2/3` OGIT families + Layer-2 axioms + style wiring), |
| 20 | +> PR #416 (FIBU/FIBO + odoo savant roster `contract::savants`), PR #407/408 |
| 21 | +> (bO-* OWL hydrators), PR #418 (mailbox-owned SoA; `E-BATON-1`), PR #419 |
| 22 | +> (25 AXIS-B evidence contracts as prose), PR #420 (v1 reasoners — deprecated |
| 23 | +> in v2). Driver epiphany: `E-SAVANT-COMPOSITION-1` (2026-05-28). |
| 24 | +> |
| 25 | +> **Anchored iron rules:** `I-VSA-IDENTITIES` (typed Layer-2 catalogues — |
| 26 | +> identity in const data, content in tables), AGI-as-glove (new column not |
| 27 | +> new layer — typed DTOs ARE the column the inheritance chain reads from), |
| 28 | +> "consult before guess" (the L-doc curation IS the curated surface; project |
| 29 | +> it into typed structure, don't re-derive). |
| 30 | +
|
| 31 | +## The diagnosis |
| 32 | + |
| 33 | +lance-graph has shipped most of the cognitive substrate: |
| 34 | +- OGIT families + Layer-2 axioms (PR #414/416), OWL hydrators (PR #407/408), |
| 35 | + DOLCE classifier (PR #412), FIBU/FIBO alignment (PR #416) |
| 36 | +- 33-TSV atoms + 34 `Tactic` kernels + `jit::{JitCompiler, StyleRegistry, KernelHandle}` (PR #411) |
| 37 | +- `CausalEdge64` (`causal-edge` v0.2.0) + `cognitive-shader-driver` |
| 38 | +- 25-savant roster in `contract::savants` (PR #416) |
| 39 | +- 15 lane drafts (`.claude/odoo/L*.md`, PR #413) + 25 AXIS-B evidence |
| 40 | + contracts (`.claude/odoo/savants/*.md`, PR #419) — **as prose** |
| 41 | + |
| 42 | +**Missing layer**: typed Odoo entity DTOs that the inheritance chain |
| 43 | +(Odoo → OGIT → OWL → DOLCE → FIBU/FIBO) operates on. Today every |
| 44 | +downstream layer string-keys against `model_name`. There is no shared |
| 45 | +typed representation of "what an Odoo entity *is*" — its fields, methods, |
| 46 | +decorators, state machine, constraints. The user-named pipeline: |
| 47 | + |
| 48 | +``` |
| 49 | +Odoo source (exact = ground truth) |
| 50 | + → typed Odoo entity DTOs ← THIS PLAN |
| 51 | + → normalize: Odoo → OGIT → OWL → DOLCE → FIBU/FIBO inheritance chain |
| 52 | + → recipes (34 Tactic kernels) + JITson / Cranelift codegen |
| 53 | + → DTO-ish NARS atoms (33-TSV) — low-entropy typed surface |
| 54 | + → cognitive-shader-driver fans across the SoA at 10000×10000 |
| 55 | + → CausalEdge64 emissions in EdgeColumn = the conclusions |
| 56 | +``` |
| 57 | + |
| 58 | +## Scope (decisions ratified 2026-05-28) |
| 59 | + |
| 60 | +- **Source**: Both passes — L-docs first as the savant-relevant curated |
| 61 | + filter; Odoo source extraction follows as the exhaustive backing. |
| 62 | +- **Lane coverage**: All 15 lanes (L1–L15) in v1. Complete typed blueprint |
| 63 | + of the Odoo domain, not a savant-rich subset. |
| 64 | + |
| 65 | +## The typed DTO surface (agnostic primitives) |
| 66 | + |
| 67 | +New module: **`lance-graph-ontology::odoo_blueprint`** (sits next to the |
| 68 | +existing odoo hydrator + `dolce_odoo`). Zero-dep beyond what ontology |
| 69 | +already pulls, all const data, no serde: |
| 70 | + |
| 71 | +```rust |
| 72 | +pub struct OdooEntity { |
| 73 | + pub model_name: &'static str, // "account.fiscal.position" |
| 74 | + pub description: &'static str, // one-line semantic intent |
| 75 | + pub fields: &'static [OdooField], |
| 76 | + pub methods: &'static [OdooMethod], |
| 77 | + pub decorators: &'static [OdooDecorator], |
| 78 | + pub state_machine: Option<&'static OdooStateMachine>, |
| 79 | + pub constraints: &'static [OdooConstraint], |
| 80 | + pub provenance: OdooProvenance, // L-doc lines + Odoo source paths |
| 81 | +} |
| 82 | +pub struct OdooField { |
| 83 | + pub name: &'static str, |
| 84 | + pub kind: OdooFieldKind, // Char / Many2one / One2many / Many2many / Selection / ... |
| 85 | + pub target: Option<&'static str>, |
| 86 | + pub required: bool, |
| 87 | + pub computed: Option<&'static str>, |
| 88 | + pub depends: &'static [&'static str], // @api.depends targets |
| 89 | + pub semantic_role: OdooSemanticRole, // Identity / Reference / Quantity / Date / Policy / ... |
| 90 | +} |
| 91 | +pub struct OdooMethod { |
| 92 | + pub name: &'static str, // "_compute_fiscal_position", "action_post", ... |
| 93 | + pub kind: OdooMethodKind, // Compute / Inverse / Constrain / Onchange / Action / Cron / ApiModel / ... |
| 94 | + pub return_kind: OdooReturnKind, // Unit / Self_ / Record / Recordset / Bool / Number / ... |
| 95 | + pub triggers: &'static [&'static str], // state transitions this method fires (if Action) |
| 96 | +} |
| 97 | +pub struct OdooDecorator { |
| 98 | + pub kind: OdooDecoratorKind, // ApiDepends / ApiConstrains / ApiOnchange / ApiModelCreateMulti / ... |
| 99 | + pub targets: &'static [&'static str], |
| 100 | +} |
| 101 | +pub struct OdooStateMachine { |
| 102 | + pub state_field: &'static str, // typically "state" |
| 103 | + pub states: &'static [OdooState], |
| 104 | + pub transitions: &'static [OdooTransition], |
| 105 | +} |
| 106 | +pub struct OdooState { pub name: &'static str, pub semantic: OdooStateSemantic /* Draft/Active/Completed/Cancelled/Terminal/... */ } |
| 107 | +pub struct OdooTransition { pub from: &'static str, pub to: &'static str, pub trigger: &'static str, pub guards: &'static [&'static str] } |
| 108 | +pub struct OdooConstraint { pub kind: OdooConstraintKind /* Sql/Python(@api.constrains)/Domain/... */, pub condition: &'static str, pub source_method: Option<&'static str> } |
| 109 | +pub struct OdooProvenance { |
| 110 | + pub l_doc: &'static str, // "L9-PARTNER-FISCALPOS.md" |
| 111 | + pub l_doc_lines: (u32, u32), |
| 112 | + pub odoo_source: &'static [(&'static str, u32, u32)], // (path, start, end), multi if entity spans files |
| 113 | + pub confidence: OdooConfidence, // Curated / Extracted / Conjecture |
| 114 | +} |
| 115 | +``` |
| 116 | + |
| 117 | +The inheritance chain operates on this typed DTO as input — replacing today's |
| 118 | +string-keyed lookups. |
| 119 | + |
| 120 | +## Deliverables |
| 121 | + |
| 122 | +| D-id | Scope | Crate | Lines | Conf | Status | |
| 123 | +|---|---|---|---|---|---| |
| 124 | +| **D-ODOO-BP-1a** | `OdooEntity` + sub-types (zero-dep, const-only, no serde) — the typed surface | `lance-graph-ontology` | 300 | HIGH | Queued | |
| 125 | +| **D-ODOO-BP-1b** | L-doc projection: one `OdooEntity` const per entity in each L-doc, 15 lanes, per-lane module `odoo_blueprint::l{1..15}`, provenance=Curated, line-range citations | `lance-graph-ontology` | 2500 | HIGH | Queued | |
| 126 | +| **D-ODOO-BP-1c** | Wire OGIT classifier to take `&OdooEntity` (replaces string-keyed `resolve_odoo`); uses field/method semantics for richer dispatch; covers 0x63/0x90 from PR #414 | `lance-graph-ontology` + `lance-graph-callcenter::family_table` | 250 | HIGH | Queued | |
| 127 | +| **D-ODOO-BP-1d** | Wire OWL hydrator to take `&OdooEntity`: relational fields → edges, computed fields → SHACL-equivalent constraints, decorators → axioms | `lance-graph-ontology` | 350 | MED | Queued | |
| 128 | +| **D-ODOO-BP-1e** | Wire DOLCE classifier + FIBU/FIBO alignment to take `&OdooEntity`; close out D-ODOO-SAV-2's `None`-class alignment for `stock.*` / `analytic.distribution.model` / `account.account.tag` over typed input | `lance-graph-ontology` | 200 | HIGH | Queued | |
| 129 | +| **D-ODOO-BP-1f** | Odoo source extraction tool: walk `/home/user/odoo`, parse Python AST for ORM classes via tree-sitter, emit candidate `OdooEntity` consts with `Confidence=Extracted`; merge into 1b's curated set as a follow-up validation pass | `tools/odoo-blueprint-extractor/` | 800 | MED | Queued | |
| 130 | +| **D-ODOO-BP-1g** | Wire JITson → recipes: `jit::JitCompiler` compiles `Tactic` kernels parameterized by `(OdooEntity, AtomTouchMask)`; produces the DTO-ish NARS that lands in the shader-driver | `lance-graph-contract::jit` + `thinking-engine` | 400 | MED | Queued | |
| 131 | + |
| 132 | +## Execution |
| 133 | + |
| 134 | +1. **D-ODOO-BP-1a first** — typed surface. Ships with this plan + board |
| 135 | + hygiene (INTEGRATION_PLANS prepend + STATUS_BOARD section). Additive. |
| 136 | +2. **D-ODOO-BP-1b in waves** — one Wave per lane group (L1–L5, L6–L10, |
| 137 | + L11–L15), one subagent per lane (Sonnet, mechanical projection of |
| 138 | + prose → const data, Tier-0 reads of L-doc + savant docs). ~5 entities |
| 139 | + per lane average × 15 lanes ≈ 75–200 consts. Per-lane PRs land |
| 140 | + independently once 1a is in. |
| 141 | +3. **D-ODOO-BP-1c/d/e in parallel after 1b** — three inheritance-chain |
| 142 | + hops, independent, each takes `&OdooEntity` as the typed input. |
| 143 | + Replaces the current ad-hoc string maps. |
| 144 | +4. **D-ODOO-BP-1f after 1b/c/d/e** — source extractor validates the |
| 145 | + curated set + extends to non-savant-relevant entities. Conflicts |
| 146 | + (curated vs extracted) flag for human ratification. |
| 147 | +5. **D-ODOO-BP-1g closes the loop** — JITson compiles `Tactic` kernels |
| 148 | + over the normalized `OdooEntity` → DTO-ish NARS in the shader. |
| 149 | +6. **THEN `odoo-savant-reasoners-v2` Group F** is unblocked — per-savant |
| 150 | + `SavantPattern` consts compose over the normalized chain. |
| 151 | + |
| 152 | +`odoo-savant-reasoners-v2` Groups D/E/G remain unblocked by this plan |
| 153 | +(they ship independently; F is the only group blocked on the blueprint). |
| 154 | + |
| 155 | +## Open questions / risks |
| 156 | + |
| 157 | +- **L-doc completeness vs Odoo source ground truth**: L-docs are |
| 158 | + human-curated samples; entities the savants need may be partially |
| 159 | + documented. 1f extraction backs them up. If a curated entity disagrees |
| 160 | + with an extracted one, default to the curated (humans filtered for |
| 161 | + relevance) and flag in `OdooProvenance` for review. |
| 162 | +- **Const data binary size**: ~150-300 entities × ~20 fields + methods |
| 163 | + + decorators could grow the binary. Mitigation: feature-gate per-lane |
| 164 | + modules (`odoo-blueprint-l9` etc.) so consumers pull only what they |
| 165 | + need; default-on for all lanes for the build-once developer experience. |
| 166 | +- **Provenance drift**: L-doc edits would desync the const data. v1f |
| 167 | + extractor becomes the long-term ground truth; v1b is the validated |
| 168 | + cache that re-syncs on demand. |
| 169 | +- **OdooSemanticRole / OdooStateSemantic enum coverage**: the enum |
| 170 | + variants must cover what the 15 lanes surface without trailing |
| 171 | + `Other(string)` escape hatches. Mitigation: 1b projection drives |
| 172 | + enum-variant discovery; expand the enums per-Wave, freeze after L15. |
| 173 | +- **JITson wiring (1g)**: `jit::JitCompiler` exists but isn't wired |
| 174 | + to recipes yet. Scope-creep risk into Cranelift kernel templates. |
| 175 | + Mitigation: 1g produces ONE proof-of-concept JIT path (FiscalPositionResolver), |
| 176 | + the rest follow in `odoo-savant-reasoners-v2` Group F. |
| 177 | + |
| 178 | +## Invariants |
| 179 | + |
| 180 | +- Zero-dep, const-only, no serde on the DTO surface (AGI-as-glove + |
| 181 | + contract discipline). |
| 182 | +- Provenance on EVERY entity (`I-VSA-IDENTITIES`: content in typed |
| 183 | + registries, never bundled — the const IS the registry). |
| 184 | +- Inheritance chain operates on typed DTOs, **never on string model |
| 185 | + names** (kills the ad-hoc lookup tax). |
| 186 | +- L-doc projection is the canonical v1 source; Odoo source extraction |
| 187 | + is validation/extension. |
| 188 | +- This blueprint is **PREREQUISITE for `odoo-savant-reasoners-v2` |
| 189 | + Group F**; v2's composition layer composes ON TOP of normalized DTOs. |
| 190 | +- Board hygiene: this plan + INTEGRATION_PLANS PREPEND + STATUS_BOARD |
| 191 | + section land in the same commit as D-ODOO-BP-1a (per CLAUDE.md |
| 192 | + Mandatory Board-Hygiene Rule). |
0 commit comments