forked from lance-format/lance-graph
-
Notifications
You must be signed in to change notification settings - Fork 0
docs(odoo): import Odoo savant briefing pack into .claude/odoo #413
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| # Odoo Richness Harvest — GAP Lanes (L8–L15) + Savant-Agent Goal | ||
|
|
||
| > Companion to `.claude/odoo/BRIEFING.md` (read it first — the dual-axis | ||
| > classification, ontology shape, reading discipline, and output template all | ||
| > apply unchanged). This file defines the **remaining** lanes after L1–L7 and | ||
| > the end-goal those lanes feed: **Savant agents**. | ||
| > | ||
| > You are ONE read-only analysis lane. Output is a markdown spec draft only. | ||
| > **No cargo, no `src/` edits, no git.** Write exactly one file to | ||
| > `/home/user/woa-rs/.claude/odoo/<your-lane>.md`. First line MUST be | ||
| > `RICHNESS-LANE-OK`; last section MUST be the depth-proof footer | ||
| > (`Read: <file> lines=<n> depth=full` per file). | ||
|
|
||
| ## What L1–L7 already covered (do NOT re-harvest) | ||
|
|
||
| | Lane | Covered | | ||
| |---|---| | ||
| | L1 | K3 double-entry posting (`account.move` state machine, `_check_balanced`, hash) | | ||
| | L2 | K3 reconciliation matching (open-item ↔ payment) | | ||
| | L3 | K7 USt/VAT compute + fiscal-position mapping (tax compute core) | | ||
| | L4 | K8 German report line-mappings + K9 DATEV export | | ||
| | L5 | Payments, payment terms, reconcile-model matching rules | | ||
| | L6 | Sale + Purchase order → invoice flow (Vorgang lifecycle) | | ||
| | L7 | Inventory: stock moves, picking, quant valuation + reservation | | ||
|
|
||
| ## The remaining lanes (assigned per agent) | ||
|
|
||
| Odoo community source root: `/home/user/odoo/addons/` — present modules: | ||
| `account, hr, l10n_de, product, purchase, sale, stock`. Enterprise modules | ||
| (`account_asset`, `hr_payroll`, `account_reports`, `account_consolidation`) | ||
| are **absent** — flag, do not hallucinate; spec only base data/structure. | ||
|
|
||
| | Lane | Subsystem | Primary odoo files (read FULLY) | woa-rs K-target | | ||
| |---|---|---|---| | ||
| | **L8** | Product + UoM + Pricelist + costing | `product/models/product_template.py`, `product_product.py`, `product_category.py`, `product_pricelist.py`, `product_pricelist_item.py`, `uom/models/uom_uom.py` | data foundation; pricing (Vorgang line price), costing config (K3 valuation) | | ||
| | **L9** | Partner accounting properties + fiscal-position assignment | `account/models/partner.py` (res.partner extensions: `property_account_receivable_id`, `property_payment_term_id`, `property_account_position_id`, `_get_fiscal_position`, `commercial_partner_id`), base `res.partner` accounting fields | data foundation; partner→tax-mapping inference (AXIS-B) | | ||
| | **L10** | Analytic accounting (Kostenstellen) | `analytic/models/analytic_account.py`, `analytic_line.py`, `analytic_plan.py`, `analytic_distribution_model.py`; `account/models/account_move_line.py` analytic_distribution | new K-area: cost-centre allocation; distribution-model rules (AXIS-B) | | ||
| | **L11** | Chart of accounts + journals + lock dates + sequences | `account/models/account_account.py` (`account_type`, `reconcile`, `internal_group`), `account_group.py`, `account_journal.py`, `account/models/company.py` lock-date logic (`fiscalyear_lock_date`, `tax_lock_date`, `_get_violated_lock_dates`), `sequence_mixin.py` | K11 lock-date semantics + K3 sequence format families | | ||
| | **L12** | Multi-company + multi-currency | base `res.company`, `res.currency` + `res.currency.rate` (`_convert`, `_get_conversion_rate`, rounding), `account_move_line.py` `amount_currency`/`balance` compute, multi-company record rules | K15 Mehrfirma + multi-currency | | ||
| | **L13** | Stock↔Accounting valuation bridge + procurement | `stock/models/stock_valuation_layer.py`, `product/models/product.py` valuation (`_run_fifo`, `_run_average`, standard), `stock/models/stock_rule.py`, `stock_warehouse_orderpoint.py`, `stock_lot.py` | bridges stock→K3 (inventory GL postings); reordering (AXIS-A formula + AXIS-B) | | ||
| | **L14** | HR base data (employee/org/contract structure) | `hr/models/hr_employee.py`, `hr_department.py`, `hr_job.py`, `hr_contract.py` (base only) | K13 **data foundation** only — payroll ENGINE is Enterprise (absent) → built fresh; flag | | ||
| | **L15** | Tax repartition + tax groups + price_include + cash-basis | `account/models/account_tax.py` (`repartition_line_ids`, `_compute_amount`, `price_include`/`include_base_amount` ordering, `account_tax_group.py`, cash-basis transition) | deepens K7/L3 — the base/tax %-split to accounts+tags | | ||
|
|
||
| ## End-goal these lanes feed: Savant agents | ||
|
|
||
| Every rule you tag **AXIS-B (heuristic → delegate)** is a candidate **Savant | ||
| agent**: a specialised reasoner defined by three coordinates. Make the | ||
| delegation tuple explicit (per `BRIEFING.md`) so the synthesis pass can mint | ||
| the Savant directly: | ||
|
|
||
| 1. **Ontology** — the odoo class → OWL pivot → OGIT family (8-bit) via | ||
| `resolve_odoo_to_family()`. State the expected family (e.g. `0x61 | ||
| BillingCore`, `0x62 SMBAccounting`) or `None` (→ "ontology-unmapped, needs | ||
| a Layer-2 alignment axiom"). | ||
| 2. **Use case** — the K-step / business question (`ReasoningKind` ∈ | ||
| {CustomerCategory, PostingAnomaly, NextBestAction, InvoiceCompleteness, | ||
| MailIntent, Other(label)}). | ||
| 3. **Thinking** — `InferenceType` ∈ {Deduction, Induction, Abduction, | ||
| Revision, Synthesis}; `SemiringChoice` ∈ {Boolean, HammingMin, NarsTruth, | ||
| XorBundle, CamPqAdc}; `ThinkingStyle`-cluster ∈ {Analytical, Creative, | ||
| Empathic, Direct, Exploratory, Meta} **inherited from the OGIT family**. | ||
|
|
||
| For each AXIS-B rule, end its entry with a one-line **Savant seed**: | ||
| `SAVANT: name=<x> family=<0x..|None> reasoning=<Kind> inference=<Type> | ||
| semiring=<Choice> style=<cluster> — <1-line why-delegated>`. | ||
|
|
||
| AXIS-A rules need no Savant — they are deterministic Rust ports; just give | ||
| the rich-AST sketch so an Opus porter can reproduce them. | ||
|
|
||
| ## Reading discipline (Iron Rule 4 / Op-rule №3) | ||
|
|
||
| Read the odoo Python **fully** with the `Read` tool (whole file or | ||
| offset/limit chunks covering the entire method). `grep`/`sed`/`head` are | ||
| locators only. Quote `file:line-range` for every rule. Odoo source is | ||
| canonical; where it's odd, note it, don't "improve". | ||
|
|
||
| ## Hard rules | ||
|
|
||
| - NO `cargo`, NO `src/` edits, NO git. Markdown only, to your one drafts file. | ||
| - First line `RICHNESS-LANE-OK`; depth-proof footer last. | ||
| - If a subsystem is Enterprise-only, say so and spec only base data/structure. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,165 @@ | ||
| # Odoo Richness Harvest — Shared Lane Briefing | ||
|
|
||
| > Read this fully before starting. You are ONE read-only analysis lane in a | ||
| > parallel fan-out. Output is a markdown spec draft only. **No cargo, no | ||
| > `src/` edits, no git.** Write exactly one file to | ||
| > `/home/user/woa-rs/.claude/board/odoo-richness/drafts/<your-lane>.md`. | ||
|
|
||
| ## Mission (two stacked user directives) | ||
|
|
||
| 1. **"Wherever odoo is richer, take the old shape and export so rich AST | ||
| details that we can reproduce the rich business logic in Rust (woa-rs), | ||
| and possibly later in Python (WoA — not yet)."** | ||
| → Where odoo's logic is *richer* than woa-rs's current ERP state, capture | ||
| the FULL behaviour — control flow, branches, field computes, ordering, | ||
| rounding, edge cases, constraints — faithfully enough that an Opus porter | ||
| can reproduce it in Rust **without re-reading the odoo source**. Keep the | ||
| ontology shape (below) attached to every concept. | ||
|
|
||
| 2. **"Check also for NARS patterns that can be delegated to thinking in | ||
| lance-graph and OGIT-inherited thinking styles for business heuristics."** | ||
| → Classify every business rule on a DUAL axis (below). Deterministic logic | ||
| gets the rich-AST treatment for a Rust port. Heuristic/inferential logic | ||
| gets flagged for *delegation* to lance-graph's thinking surface instead of | ||
| being hard-coded as Rust if/else. | ||
|
|
||
| ## The dual-axis classification (do this for EVERY rule you extract) | ||
|
|
||
| For each method / computed field / constraint, tag it: | ||
|
|
||
| - **AXIS-A — DETERMINISTIC → Rust port.** A closed-form rule: a balance | ||
| check, a sequence format, a tax = base × rate, a residual = debit − credit. | ||
| Output: rich-AST spec (see template) so it can be ported verbatim. | ||
|
|
||
| - **AXIS-B — HEURISTIC / INFERENTIAL → delegate to lance-graph thinking.** | ||
| Evidence-weighted, multi-factor, ambiguous, or "best guess" logic: | ||
| reconciliation *matching* (which open item pairs with which payment), | ||
| fiscal-position *resolution* (which tax mapping applies to this partner), | ||
| next-best-action, anomaly detection, stock reservation choice, dunning | ||
| escalation judgement. These should NOT be reproduced as brittle Rust | ||
| branches — they are delegated. | ||
|
|
||
| When you tag AXIS-B, fill the **delegation tuple** using the | ||
| `lance-graph-contract` surface (these enums already exist and are | ||
| customer-binary-safe / BBB-allowed): | ||
|
|
||
| - `ReasoningKind` ∈ { CustomerCategory, PostingAnomaly, NextBestAction, | ||
| InvoiceCompleteness, MailIntent, Other(u32) } — pick the closest; if none | ||
| fits, propose an `Other` label. | ||
| - `InferenceType` ∈ { Deduction (exact lookup), Induction (pattern/"things | ||
| like X"), Abduction (root-cause/"why"), Revision (belief update on change), | ||
| Synthesis (cross-domain join) }. | ||
| - `SemiringChoice` ∈ { Boolean, HammingMin, NarsTruth, XorBundle, CamPqAdc } | ||
| — how evidence combines (NarsTruth = evidence fusion is the common case). | ||
| - `ThinkingStyle` cluster ∈ { Analytical, Creative, Empathic, Direct, | ||
| Exploratory, Meta }. **This is INHERITED from the OGIT family**, not | ||
| chosen freely: the odoo class resolves to an OGIT `FamilyEntry` via | ||
| `resolve_odoo_to_family()` (the cache we just built — see Ontology shape), | ||
| and the family carries the default style. State which family you'd expect | ||
| and therefore which cluster; if the family is unmapped (returns `None`), | ||
| say so and propose a cluster with a one-line rationale. | ||
|
|
||
| A rule can be **hybrid**: a deterministic guard wrapping a heuristic core | ||
| (e.g. "balance MUST be zero" [AXIS-A] gating "suggest which lines to adjust" | ||
| [AXIS-B]). Tag both halves. | ||
|
|
||
| ## Ontology shape (keep it attached — directive 1's "old shape") | ||
|
|
||
| We already built the OGIT→OWL→odoo cache: | ||
| `lance-graph/crates/.../lance-graph-callcenter/src/odoo_alignment.rs` and a | ||
| mirror in `woa-rs/crates/skr_data/src/odoo_alignment.rs`. The chain is: | ||
|
|
||
| ``` | ||
| odoo class ──owl:equivalentClass──► OWL pivot (fibo/ubl/vcard/schema) ──► OGIT family (8-bit) + slot (16-bit) ──► FamilyEntry (carries thinking style) | ||
| resolve_odoo() OgitFamilyTable.lookup() = O(1) | ||
| resolve_odoo_to_family(class, &table) chains both legs end-to-end, O(1) | ||
| ``` | ||
|
|
||
| Seed rows already mapped: `res.partner.Company`→fibo:LegalEntity, | ||
| `account.move`→fibo:Transaction, `account.move.line`→fibo:JournalEntryLine, | ||
| `account.account`→fibo:Account, `product.*`→schema:Product, SKR concepts→ | ||
| fibo:Account. Families in use: 0x61 BillingCore, 0x62 SMBAccounting, | ||
| 0x80 SmbFoundryCustomer, 0x81 SmbFoundryInvoice. **Option B**: no new CAM | ||
| family, no new slot — odoo classes INHERIT an existing OGIT slot via the OWL | ||
| pivot. Classes with no existing family (`stock.move`, `sale.order`, | ||
| `hr.*`, `account.reconcile.model`, …) currently resolve to `None` — if your | ||
| lane touches one, FLAG it as "ontology-unmapped, needs a Layer-2 alignment | ||
| axiom" rather than inventing a family. | ||
|
|
||
| For each odoo concept your lane covers, record: `odoo:<class>` → | ||
| `owl:equivalentClass <pivot>` → expected OGIT family (or `None`). The | ||
| DOLCE marker (Endurant/Perdurant/Quality/Abstract) comes from `dolce_odoo()` | ||
| suffix rules; note it where non-obvious. | ||
|
|
||
| ## Reading discipline (Iron Rule 4 / woa-rs Op-rule №3) | ||
|
|
||
| - Read the odoo Python **fully** with the `Read` tool — whole file or | ||
| offset/limit chunks that cover the entire method. `grep`/`sed`/`head` are | ||
| LOCATORS only, never comprehension. A snippet read produces a paraphrase | ||
| spec that the porter then has to redo. | ||
| - Quote the odoo `file:line-range` for every rule you spec. The porter will | ||
| spot-check against the source. | ||
| - Odoo's source is **canonical** for these semantics (we are stealing them). | ||
| Where odoo is buggy or odd, note it; do not silently "improve". | ||
|
|
||
| ## ERP gap context (what woa-rs is missing — the K-steps) | ||
|
|
||
| | K-step | Subsystem | woa-rs state | | ||
| |---|---|---| | ||
| | K3 | Double-entry posting + reconciliation | engine partial / view 501 | | ||
| | K7 | USt-Voranmeldung / tax compute / ELSTER | missing | | ||
| | K8 | German reports (BWA/SuSa/EÜR/GuV/Bilanz) | missing — engine built FRESH (odoo `account_reports` is Enterprise; only l10n_de **data/line-mappings** are stealable) | | ||
| | K9 | DATEV export | partial | | ||
| | K11 | Festschreibung (GoBD period lock) | missing | | ||
| | K12 | Anlagen (asset depreciation) | missing — odoo `account_asset` is **Enterprise**, NOT in community source | | ||
| | K13 | Lohn / payroll | missing — odoo `hr_payroll` is **Enterprise**, NOT in community (only `hr` base is present) | | ||
| | K15 | Mehrfirma (multi-company) | missing | | ||
|
|
||
| **Enterprise boundary — flag, do not hallucinate.** account_asset, | ||
| account_reports, hr_payroll, account_consolidation are NOT in the community | ||
| clone. If your lane's subsystem is Enterprise-only, say so explicitly and | ||
| spec only what IS present (base models, data, report STRUCTURE) — the engine | ||
| gets built fresh on the woa-rs side. | ||
|
|
||
| ## Output template (one file, `drafts/<lane>.md`) | ||
|
|
||
| ```markdown | ||
| # Lane <ID> — <subsystem> | ||
|
|
||
| ## Sources read (file : line-range : depth) | ||
| - odoo/addons/.../x.py : L<a>-<b> : full | ||
| - ... | ||
|
|
||
| ## Ontology rows | ||
| | odoo class | owl pivot | OGIT family (or None) | DOLCE | | ||
| |---|---|---|---| | ||
|
|
||
| ## Rules extracted | ||
| ### R<n> — <name> [AXIS-A | AXIS-B | HYBRID] | ||
| - **odoo source**: file:Lx-Ly | ||
| - **What it does** (rich): <control flow, branches, ordering, rounding, edge | ||
| cases — enough to reproduce> | ||
| - **woa-rs target**: <which K-step / which model/route this lands in> | ||
| - (AXIS-A) **Rust sketch**: <signature + key branches; Decimal/money rules; no | ||
| hand-waving on rounding or sign> | ||
| - (AXIS-B) **Delegation tuple**: ReasoningKind=… InferenceType=… Semiring=… | ||
| ThinkingStyle-cluster=… (inherited from OGIT family <fam>) — rationale 1 line | ||
| - **Parity notes / gotchas**: <German-tax specifics, GoBD, multi-currency, etc.> | ||
|
|
||
| ## Enterprise gaps flagged | ||
| - <module> : <what's missing> : <what we spec from data/structure instead> | ||
|
|
||
| ## Open questions for the Opus porter | ||
| - ... | ||
| ``` | ||
|
|
||
| ## Sentinel + depth-proof (required — the agent prompts reference these) | ||
| - **First line of your draft MUST be:** `RICHNESS-LANE-OK` | ||
| - **Last section MUST be a depth-proof footer**, one line per file: | ||
| `Read: <file> lines=<n> depth=full` | ||
|
|
||
| ## Hard rules | ||
| - NO `cargo` (no build/check/clippy/test). NO `src/` edits. NO git ops. | ||
| - Markdown output only, to your one drafts file. | ||
| - If two lanes would overlap on a file, still read it fully for your angle; | ||
| the Opus review pass dedups. | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When future agents follow this newly added lance-graph-side briefing, the output target still points at
/home/user/woa-rs/..., so their drafts will be written outside this repository (or fail if that path is absent) instead of landing under.claude/odoo/.claude/boardhere. The same stale woa-rs target is repeated inBRIEFING-GAP.md, so the imported instructions need either a lance-graph-local path or an explicit note that they are historical reference-only.Useful? React with 👍 / 👎.