Skip to content

Commit 30b52e1

Browse files
authored
Merge pull request #432 from AdaWorldAPI/claude/activate-lance-graph-att-k2pHI
feat(spo): Foundry-shape emitters — codegen_spine + odoo_ontology + action_emitter + link_chain
2 parents 108bcd6 + 0e5ab98 commit 30b52e1

10 files changed

Lines changed: 25309 additions & 0 deletions

File tree

.claude/board/AGENT_LOG.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,28 @@ clean. `cargo test --lib` 472 green. `cargo test --test cognition_typestate`
5353
Created `cognition::{stages, entity, op, advance, cascade}` + `transaction::{interactive, bulk, periodisch, ctx}` modules in `lance-graph-contract` — the typed consumer pipeline grammar per `.claude/plans/normalized-entity-holy-grail-v1.md`. All advancement verbs past `resolve_ogit` have `todo!()` bodies flagged with `// TODO(Stage 2):` markers for Stage 2 wiring (markers were `/// work` in the original scaffold; converted to `// TODO(Stage 2):` in the main-thread review-strip pass that followed). Compile-fail tests in `tests/cognition_typestate.rs` plus 7 passing positive tests document the typestate gate.
5454

5555
**Branch:** `claude/normalized-entity-holy-grail-v1`, prior commit `1695a9a` (plan). commit `b96baf3`. `cargo check -p lance-graph-contract` clean (0 errors); `cargo test -p lance-graph-contract --lib` green (472 tests); `cargo test -p lance-graph-contract --test cognition_typestate` green (7 tests).
56+
## [SavantPattern / Opus 4.8] Foundry-shape SPO emitters + codegen_spine — deliverables 1+2
57+
58+
**Branch:** claude/activate-lance-graph-att-k2pHI | **Files:**
59+
- `crates/lance-graph-contract/src/codegen_spine.rs` (+565 lines new), `crates/lance-graph-contract/src/lib.rs` (+1 line `pub mod codegen_spine`)
60+
- `crates/lance-graph/src/graph/spo/odoo_ontology.rs` (+170 lines), `odoo_ontology.spo.ndjson` (+2.5 MB data, 22245 triples)
61+
- `crates/lance-graph/src/graph/spo/action_emitter.rs` (+540 lines), `link_chain.rs` (+440 lines), `mod.rs` (+3 lines)
62+
- `.claude/knowledge/foundry-workshop-elixir-rust-evaluation.md`, `semantic-operational-handbook-v0.1.md`
63+
64+
**Tests (orchestrator-verified):**
65+
- `cargo test -p lance-graph-contract --lib codegen_spine` → 6/6 (lossless/lossy roundtrip, OdooMethodKind id stability, RouteBucket trait, WidgetRender trait, Genericity marker).
66+
- `cargo test -p lance-graph --lib graph::spo::odoo_ontology` → 4/4 (parse, predicate histogram, store loading, emitted_by edge).
67+
- `cargo test -p lance-graph --lib graph::spo::action_emitter` → 9/9 (synthetic fixture + shipped ontology 3328 functions).
68+
- `cargo test -p lance-graph --lib graph::spo::link_chain` → 10/10 (5-hop decomposition + shipped ontology 6309 depends_on, 0 malformed).
69+
70+
**Outcome:** DONE. Three deterministic emitters landing the user's hardening direction "triplets <> static codegen <> askama route SoC <> askama gui shape":
71+
72+
1. **codegen_spine** — four canonical traits (`TripletProjection` + `roundtrip_eq`, `OdooMethodKind` + `RouteBucket`, `WidgetRender<B>`, `Genericity { Agnostic, Domain }`). Zero new dependencies, std-only.
73+
2. **odoo_ontology** — SPO loader for the 22245-triple Foundry-shape Odoo extraction. NARS truth values, identity-by-name fingerprints.
74+
3. **action_emitter**`Vec<ActionSpec>` per function, composing `emitted_by`/`depends_on`/`raises`/`reads_field`/`traverses_relation`. 3328 actions from shipped data.
75+
4. **link_chain**`LinkChain { source_family, hops, leaf }` decomposition of flat dotted `depends_on` paths. String-only at this layer (target-ObjectType resolution stays in consumer crate to keep crate graph acyclic).
76+
77+
**Review pattern:** each module went through build (with `/// work` markers) → opus-4.8 reviewer pass (idiomatic Rust, test coverage, marker removal) → orchestrator-run cargo verify. Reviewer-1 eliminated 4 `BTreeSet::cloned()` allocations + 2 edge-case tests; Reviewer-2 collapsed two-pass validation to single-loop + 1 `compute_stats` coverage test + 4 malformed-input assertions.
5678

5779
---
5880

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
# Evaluation: Foundry Workshop low-code on Elixir abstraction, compiled to Rust
2+
3+
> **READ BY:** agents working the Elixir frontend, Foundry-shape codegen,
4+
> Workshop/A2UI surface, or the SPO ontology consumer path.
5+
>
6+
> **Status:** EVALUATION (2026-05-28, opus-4-8 as SavantPattern). Grounded in
7+
> read files (cited file:line); honest about gaps. Companion to
8+
> `.claude/knowledge/semantic-operational-handbook-v0.1.md` (the primitive
9+
> catalogue) and the now-verified SPO ontology loader
10+
> (`crates/lance-graph/src/graph/spo/odoo_ontology.rs`, 4 tests green).
11+
>
12+
> **Deterministic only.** No LLM, no similarity, no inference. The Workshop
13+
> low-code layer resolves names against a typed ontology + dispatches
14+
> compile-time recipes; the runtime is Rust + ractor, not a model.
15+
16+
## The question
17+
18+
Can Foundry Workshop's "apps over ontology" low-code model sit on top of an
19+
**Elixir-syntax abstraction layer** whose **holy grail is compile-to-Rust
20+
underneath**? Where does the mapping hold, where does it break?
21+
22+
## The three layers, concretely
23+
24+
```
25+
Workshop low-code surface (what a domain expert authors)
26+
│ view/action/widget bound to ontology
27+
28+
Elixir-syntax abstraction (readable DSL — NOT BEAM at runtime)
29+
│ tree-sitter-elixir parse → typed resolve against ontology
30+
31+
Rust compiled underneath (the holy grail — executable semantics)
32+
│ recipe → KernelHandle → ractor mailbox → SPO store
33+
34+
SPO ontology substrate (what names resolve against)
35+
odoo_ontology.spo.ndjson → SpoStore (22 245 triples, VERIFIED)
36+
```
37+
38+
The bottom layer is **built and tested as of this session**. The top two are
39+
partially specced (`lance-graph-elixir-frontend-v1.md`) and partially gapped
40+
(below).
41+
42+
## What HOLDS (grounded in read files)
43+
44+
### 1. The ontology substrate exists and is queryable — deterministically
45+
46+
`crates/lance-graph/src/graph/spo/odoo_ontology.rs` (this session, 4 tests
47+
green) loads 22 245 triples into the existing `SpoStore`. The Foundry
48+
primitives map 1:1 onto triple classes:
49+
50+
| Foundry (Workshop) | SPO triple class | count |
51+
| --- | --- | ---: |
52+
| Object Type | `(odoo:<family>, rdf:type, ogit:ObjectType)` | 388 |
53+
| Property | `(odoo:<fam>.<field>, rdf:type, ogit:Property)` | 3 107 |
54+
| Function | `(odoo:<fam>.<fn>, rdf:type, ogit:Function)` | 3 328 |
55+
| Function dependency | `(field, depends_on, dep)` | 6 309 |
56+
| Function output | `(field, emitted_by, fn)` | 3 228 |
57+
| Link / traversal | `(fn, traverses_relation, rel)` | 11 |
58+
| Guard signal | `(fn, raises, exc:<Type>)` | 451 |
59+
60+
The "**a + b → c through d?**" query — Foundry's core Function-resolution
61+
semantics — is a deterministic graph deduction over `depends_on` +
62+
`emitted_by`, NOT a similarity search. Verified working:
63+
`account_move.amount_total emitted_by _compute_amount, depends_on
64+
{line_ids.balance, line_ids.amount_residual, currency_id, …}`.
65+
66+
### 2. The Elixir-as-surface decision is already doctrine, not invention
67+
68+
`.claude/plans/lance-graph-elixir-frontend-v1.md` (read this session) states
69+
**"The BEAM is not a runtime target — Elixir is the SURFACE only; the
70+
substrate stays typed Rust + SIMD + JIT."** This is exactly the
71+
"Elixir abstraction, compile to Rust" question — and the workspace already
72+
committed to that shape. tree-sitter-elixir parses; HM-style inference over
73+
`|>` pipelines resolves types; the target is `lance-graph-contract::cognition`
74+
calls. 9 stages, 5 verbs, ~50 OpKind discriminants per domain.
75+
76+
### 3. The recipe hot-load protocol matches Workshop's add-without-redeploy
77+
78+
`crates/lance-graph-contract/src/recipe.rs:28-35` (read this session) defines
79+
the Elixir open/closed split:
80+
- `add-atom` = **data** change (new row in the LOCKED 33-dim basis, no recompile)
81+
- `add-style`/`add-persona` = **template** change (register a `RecipeTemplate`
82+
→ JIT `KernelHandle` at next activation)
83+
84+
This is precisely Workshop's promise: a power-user adds an Action or Function
85+
without a platform redeploy. The recipe layer is the compile-time analogue of
86+
Workshop's runtime action registry.
87+
88+
### 4. The mailbox IS Foundry Automate, actor-native
89+
90+
The 400 ms ractor mailbox + SurrealQL kanban ("request-lose Goalstate
91+
Maschine", `EPIPHANIES.md E-FOUNDRY-LAYER-1`) is the actor-native form of
92+
Foundry Automate: object-change → goal-card → mailbox resolves → action
93+
staged/applied → audit. Foundry does this as a runtime service; this stack
94+
does it as supervised actors. Equivalent operational loop, different
95+
substrate.
96+
97+
## What BREAKS / is GAPPED (honest)
98+
99+
### Gap 1 — Workshop's widget/view layer has NO ontology-native primitive
100+
101+
The existing `ruff_python_dto_check::codegen` (read this session:
102+
`codegen/jinja.rs:1-12`, `codegen/columns.rs:1-20`) is **Flask→askama HTML
103+
translation**`<table>{% for %}` extraction, `_translate_cell_expr`,
104+
`elif→else-if`. That is route-handler HTML view generation, NOT
105+
ontology-bound widgets. Workshop widgets (`object table`, `object view`,
106+
`action button`, `kanban`, `scenario`) bind to Object Types + Actions, not to
107+
jinja templates.
108+
109+
**Consequence:** the `view` primitive in the handbook (§5) has no existing
110+
emitter. Building it is NOT a reuse of the jinja codegen — it is a new
111+
ontology→widget emitter. Do not conflate them (this was a category error
112+
earlier in the session).
113+
114+
### Gap 2 — Actions exist as openings, but `requires{}` / `effects{}` are unsplit
115+
116+
The 16 openings (`.claude/odoo/openings_hops.py`, this session) classify
117+
3 555 methods into named verbs (`iter_records_compute_from_related`,
118+
`iter_records_raise_on_violation`, …). But a Foundry Action needs the
119+
guard/effect split: `requires { precondition }` + `effects { mutation }`.
120+
The openings give the *shape* (e.g. `iter_records_raise_on_violation` = a
121+
guard that raises); they do NOT yet emit the structured
122+
`requires{}`/`effects{}` blocks. The `raises` triples (451) are the guard
123+
signal; the `emitted_by`/`writes` are the effect signal — both are in the SPO
124+
graph now, but the Action-DSL emitter that composes them is unbuilt.
125+
126+
### Gap 3 — Submission criteria / governance has no Odoo-extracted primitive
127+
128+
Foundry Actions carry submission criteria (user/role/object/relation
129+
permissions). The Odoo extraction has `@api.constrains` validators (data
130+
integrity) but NOT the user-permission layer — Odoo `ir.model.access` /
131+
record rules live in XML/CSV, not in the method bodies the harvest read.
132+
**The governance spine is absent from the current extraction.** It would need
133+
a second extraction pass over Odoo's security CSVs.
134+
135+
### Gap 4 — depends_on hop chains are stored as flat strings, not resolved links
136+
137+
`account_move.amount_total depends_on
138+
line_ids.matched_debit_ids.debit_move_id.move_id.line_ids.amount_residual`
139+
— that 5-hop dotted path is stored as ONE object string. It is a real link
140+
chain (Foundry would resolve each segment to a Link traversal across Object
141+
Types), but the current emitter does not split it into per-hop
142+
`(ObjectType, link, ObjectType)` triples. The chain is queryable as a literal
143+
but not yet as a traversable link path. Splitting it requires the
144+
relation-target table (which model `line_ids` points at) — partially in the
145+
`OdooEntity` consts (`odoo_blueprint/extracted/`), not yet joined.
146+
147+
## Verdict
148+
149+
**The Elixir-on-Rust-with-Foundry-Workshop shape is sound and the bottom two
150+
layers are real**, not vapor:
151+
152+
- The SPO ontology substrate is built + tested (this session).
153+
- The Elixir-surface/compile-to-Rust decision is committed doctrine.
154+
- The recipe hot-load + ractor mailbox are the Workshop-action + Automate
155+
analogues, actor-native and compile-first.
156+
157+
**The top layer (Workshop widgets) and the Action guard/effect split are the
158+
real unbuilt work** — and crucially, the existing jinja codegen is NOT a
159+
shortcut to them (it is HTML-route translation, a different domain).
160+
161+
The honest one-line assessment:
162+
163+
> Foundry operationalizes ontology at **runtime** via a governed platform.
164+
> This stack compiles ontology into **executable Rust semantics** at build
165+
> time, dispatched by actors. The ontology spine + dependency graph are
166+
> done; the widget surface + the governance/permission spine are the gaps.
167+
168+
## Concrete next deliverables (deterministic, no model)
169+
170+
1. **Action guard/effect emitter** — compose `raises` (guard) + `emitted_by`
171+
(effect) per opening into `requires{}`/`effects{}` blocks. Input: the SPO
172+
graph (built). Output: one Action spec per (family, opening).
173+
2. **Link-chain splitter** — join `depends_on` dotted paths against the
174+
`OdooEntity` relation-target table (`odoo_blueprint/extracted/`) to emit
175+
per-hop `(ObjectType, link, ObjectType)` triples. Makes the dependency
176+
graph traversable as Foundry Links.
177+
3. **Governance extraction (second pass)** — read Odoo `ir.model.access.csv` +
178+
record rules → `(role, may_execute, action)` triples. Closes Gap 3.
179+
4. **Workshop widget emitter** — ontology Object Type → object-table /
180+
object-view / action-button widget spec. New emitter, NOT the jinja path.
181+
This is the largest unbuilt piece.
182+
183+
Each consumes the SPO ontology that is now in the store, and each is
184+
deterministic graph→spec emission.

0 commit comments

Comments
 (0)