Skip to content

Commit dd731bd

Browse files
committed
feat(contract)+docs: E-OGAR-IS-FOUNDRY capstone + 5+3 council corrections + the key->row baton
Foundry/Gotham reduces to "write the OGAR class schema + inheritance"; every other layer is generic machinery over it: ontology=classid->ClassView+inheritance, AR behavior=DO/THINK (ActionDef vs MethodSig), pipelines=compute_dag, apps=Jinja-over-classes (class_id->ontology seam), query=Cypher<->SurrealQL one IR. Captured as E-OGAR-IS-FOUNDRY. 5+3 council on cypher-kanban-ast-unification-v1 (8/8): core thesis SOUND (StepDomain::Kanban exists; 4 polyglot parsers already share one PlanInput IR). Corrections applied: - CATCH-CRITICAL (baton-auditor): MailboxSoaView had no key->row resolver. Added row_for_local_key(local_key) -> Option<usize> as a deferred-binding default-None method (matches the qualia/episodic_witness deferral pattern). +1 test, clippy clean. - from_guid_prefix is on NiblePath (hhtl.rs:262), not NodeGuid — corrected in the epiphany + plan. - "odoo existence proof" downgraded FINDING->CONJECTURE (tagged const + classify, not a running traversal); ogar-adapter-surrealql is not a crate (surreal_container stub, BLOCKED(C)). - headline demoted "four sides of one AST" -> "one IR, four relationships". - resequenced: first shippable = Inc0+F1/F2 on the Native path; Inc1 Cypher->SurrealQL is dependency-on lite-unified OQ-LU-2, not a duplicate. Three ripple boundaries pinned. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CcpLeEC3XK8Eye53GKBVvi
1 parent 8809ec5 commit dd731bd

3 files changed

Lines changed: 71 additions & 0 deletions

File tree

.claude/board/EPIPHANIES.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,28 @@
1+
## 2026-06-18 — E-OGAR-IS-FOUNDRY — being Palantir Foundry / Gotham reduces to "write the OGAR class schema + inheritance"; everything else (traversal, query, pipelines, actions, low-code apps) is generic machinery over it via the shared AST
2+
3+
**Status:** FINDING (capstone; operator-stated). The platform-level reading of the whole arc: Foundry/Gotham is not a platform to rebuild — it is an **OGAR class-schema-inheritance exercise**, because every other Foundry/Gotham layer is already generic machinery the workspace ships, parameterized only by `classid`.
4+
5+
**The reduction (each Foundry/Gotham layer → an OGAR primitive already in code):**
6+
7+
| Foundry / Gotham layer | OGAR primitive | Shipped surface |
8+
|---|---|---|
9+
| **Ontology** (object types + links) | OGAR **class schema + inheritance** | `classid → ClassView`; `effective_actions` / effective-methods = inheritance |
10+
| **Objects + links** | GUID node + `EdgeBlock` edge | `E-GUID-IS-THE-GRAPH` (key=node, slot=edge, zero-value-decode) |
11+
| **AR object behavior** | **DO vs THINK = Active Record** | THINK = `ClassView`/`MethodSig` (fields+methods, read/compute); DO = `ActionDef`/`ActionInvocation` (actions, gated RBAC→state-guard→MUL) |
12+
| **Pipelines / transforms** | `compute_dag` topological recompute | `ClassView::compute_dag` + `compute_dag_topo_order` (`E-EXCEL`/`E-CHESS`/`E-PERTURBATION`) |
13+
| **Apps / low-code / dashboards** | **Jinja/templates over OGAR classes** | `soa_view.rs:57` — `class_id → OGIT ontology → "label inheritance, column projection, jinja templates"` resolve one layer up |
14+
| **Query / traversal surface** | **Cypher ⇄ SurrealQL, one shared AST** | `E-CYPHER-IS-THE-KANBAN-AST`; polyglot parsers → one `PlanInput` IR; SurrealQL is egress |
15+
16+
**The headline:** AR-shaped DO/THINK objects + the shared Cypher/SurrealQL AST mean **any low-code or Jinja template runs over OGAR classes** without bespoke per-app wiring — the template binds to the class's fields (THINK) and actions (DO), the AST traverses/queries/mutates them, `compute_dag` recomputes derived fields, the DO-arm gate authorizes writes. So a vertical (medical / work-orders / intelligence cases / project boards) = *write its OGAR classes + inheritance*, and the platform behaviors fall out. That is the Foundry-aspiring superpower: the reduction of "build a platform" to "declare a schema."
17+
18+
**Scope guard (truth-architect, carried from the 5+3 on the sibling plan):** "everything else is shipped" is the *architecture*, not "all wired today." The honest gaps the council found: (a) `ogar-adapter-surrealql` is NOT a crate — the nearest is `surreal_container::SurrealStore` (a `BLOCKED(C)` stub); the Cypher→SurrealQL lowering rides `lite-unified` (#540, default-OFF). (b) the "odoo ontology traversal already runs through SurrealQL" claim is a tagged `const ActionDef` + `classify_odoo` classification, **not** a running end-to-end traversal — CONJECTURE, not FINDING, until an `ExecTarget::SurrealQl` executor arm exists. (c) Jinja-over-classes is the `class_id→ontology` seam (real hook) + `lance-graph-ontology` resolution — the template *engine* binding is not yet a shipped path. The reduction is the doctrine; the wiring is the `cypher-kanban-ast-unification-v1` increments. Cross-refs: `E-CYPHER-IS-THE-KANBAN-AST`, `E-GUID-IS-THE-GRAPH`, `E-AR-DO-WIRING` (DO/THINK arms), `cypher-kanban-ast-unification-v1`, `canonical_node`/`class_view`/`action`/`soa_view`.
19+
20+
---
21+
122
## 2026-06-18 — E-CYPHER-IS-THE-KANBAN-AST — a kanban board IS a graph, so Cypher is its AST; board-ops + ontology-traversal + thinking-style dispatch + SurrealQL egress collapse to ONE shared AST
223

24+
**Council correction (2026-06-18, 5+3 on `cypher-kanban-ast-unification-v1`):** three legs of this entry were over-stated and are hereby qualified (the CORE — board-is-graph, Cypher-is-graph-AST — stands; convergence-architect confirmed 3 of 4 sides share one shipped `PlanInput` IR): **(1)** "one AST seen from four sides" → say **"one IR, four *relationships*"** (surface = Cypher; egress = SurrealQL; planner-layer = thinking-styles; mutated = board) — they are *is* / *lowers-to* / *plans-over* / *is-mutated-by*, not one identity (dilution-collapse-sentinel). **(2)** "odoo ontology traversal already runs through the SurrealQL AST adapter — existence proof" is **CONJECTURE, not FINDING**: it is a tagged `const ActionDef`(`ExecTarget::SurrealQl`) + `classify_odoo`, with NO executor arm and NO Cypher→SurrealQL lowering in source; `ogar-adapter-surrealql` is not a crate (truth-architect + runtime-archaeologist). **(3)** `from_guid_prefix` lives on **`NiblePath`** (`hhtl.rs:262`), NOT `NodeGuid`; and the wiring is **blocked CATCH-CRITICAL** until `MailboxSoaView` gains a key→row resolver (`row_for_local_key`, now added default-`None`) — the View had only `n_rows`, no way back from the canon address to a row (baton-handoff-auditor). Preserve the distinction `E-GUID` correction #2 drew: mailbox-cycle `KanbanColumn` phase-advance (traversal *dispatched-within* `CognitiveWork`) ≠ domain-board column move (an edge-rewrite) — same AST surface, two semantics (ripple-architect).
25+
326
**Status:** FINDING (convergence; odoo is the existence proof — ontology traversal already runs through the SurrealQL AST adapter). Refines `E-GUID-IS-THE-GRAPH` correction #2: "kanban is lifecycle, not traversal" was a false dichotomy — the lifecycle state-machine IS a graph, and that's the whole point.
427

528
**The collapse:** a kanban board is a graph, full stop —

.claude/plans/cypher-kanban-ast-unification-v1.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,3 +105,20 @@ traversal is Cypher over `Backend::MailboxSoa`.
105105
`kanban::{KanbanColumn, ExecTarget}`, planner `thinking/` +
106106
`strategy/cypher_parse.rs`, `graph_router::Backend`,
107107
`.claude/rules/architectural-compliance.md` (q2 must consume, not substitute).
108+
109+
---
110+
111+
## 5+3 Council verdict (2026-06-18) — revisions applied
112+
113+
8/8 reported. Core thesis **SOUND** (convergence: `StepDomain::Kanban` exists; all 4 polyglot parsers already return one `PlanInput`/`QueryFeatures` IR — 3 of 4 sides are genuinely one IR). Revisions:
114+
115+
1. **Headline demoted** (dilution-sentinel): "four sides of one AST" → **"one IR, four *relationships*"** (surface=Cypher / egress=SurrealQL / planner-layer=styles / mutated=board).
116+
2. **CATCH-CRITICAL fixed first** (baton-auditor): `MailboxSoaView` had no key→row resolver — added `row_for_local_key(local_key) -> Option<usize>` default-`None` (deferred binding). `from_guid_prefix` is on **`NiblePath`** (`hhtl.rs:262`), not `NodeGuid` — Inc 0 routes via `NiblePath::from_guid_prefix(&guid)` + `NodeGuid::local_key` + `MailboxSoaView::row_for_local_key`.
117+
3. **Resequenced** (integration-lead): **first shippable = Inc 0 + F1/F2 ALONE**, on the DataFusion-default `ExecTarget::Native` path — zero SurrealQL, zero `lite-unified`, zero q2 coupling. **Inc 1 (Cypher→SurrealQL) is a *dependency-on* `lite-unified-v1`'s OQ-LU-2, NOT a duplicate deliverable** (the two plans were claiming the same lowering).
118+
4. **Three boundaries to pin before Inc 0 lands** (ripple-architect):
119+
- **(b) edge-representation is `classid`-resolved, not query-guessed:** a relationship-type binds to `EdgeBlock` (adjacency) XOR `CausalEdge64` (causal) via the class's `EdgeCodecFlavor`/`ReadMode` — the router must not pick by availability.
120+
- **(a) domain-board transition schema ≠ `KanbanColumn`:** a domain board's legal moves resolve via `classid → ClassView`, NOT `KanbanColumn::can_transition_to` (that encodes the *mailbox* Rubicon DAG only). Same graph shape, different transition algebra.
121+
- **(d) board mutation routes through the DO arm:** a move = `ActionInvocation` through the commit gate (def-match→RBAC→state-guard→MUL), NOT a raw `MATCH…SET` edge-rewrite — otherwise WIP/permission/MUL guards are bypassed. Add F6: an illegal move fails at plan time for ALL guard classes, not just Rubicon legality.
122+
5. **Status downgrades** (truth-architect + archaeologist): the "odoo existence proof" is a tagged `const` + `classify_odoo`, NOT a running traversal → CONJECTURE; "zero-value-decode" (F2) is design-intent until the value-access counter exists; `ogar-adapter-surrealql` is not a crate (it's `surreal_container::SurrealStore`, a `BLOCKED(C)` stub).
123+
124+
**Net first increment (this PR):** the `row_for_local_key` deferred-binding contract method (the named dropped baton) — additive, zero-dep, testable now. `Backend::MailboxSoa` (Inc 0 proper) follows once the three boundaries above are pinned.

crates/lance-graph-contract/src/soa_view.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,26 @@ pub trait MailboxSoaView {
6868
self.entity_type()[row]
6969
}
7070

71+
/// Resolve a canonical [`NodeGuid::local_key`](crate::canonical_node::NodeGuid::local_key)
72+
/// (bytes 10..16 = family++identity, the basin-local discriminator) to a row
73+
/// index in this view — the **key→row baton** a `Backend::MailboxSoa` graph
74+
/// router needs to land a Cypher `MATCH`/edge-slot deref on the GUID-keyed
75+
/// substrate (`cypher-kanban-ast-unification-v1` Inc 0; the baton-handoff-auditor's
76+
/// CATCH-CRITICAL — the View previously exposed only `n_rows`, with no way to go
77+
/// from the canon address back to a row).
78+
///
79+
/// **Default = `None` (zero-fallback, deferred binding).** A view that has NOT
80+
/// materialized a per-row key index returns `None` for every key — the same
81+
/// deferred-accessor discipline as `qualia` / `episodic_witness` below: the
82+
/// resolver contract is declared here so the router signature can name it, and an
83+
/// owner that stores keys (the in-RAM `MailboxSoA`, once it carries a `local_key`
84+
/// column) overrides this. Until then a consumer that gets `None` falls back to
85+
/// the positional `(mailbox_id, row)` address, never a wrong row.
86+
#[inline]
87+
fn row_for_local_key(&self, _local_key: u64) -> Option<usize> {
88+
None
89+
}
90+
7191
// NOTE (follow-up): the qualia column (`QualiaI4_16D`) accessor is intentionally omitted —
7292
// add `fn qualia(&self) -> &[crate::qualia::QualiaI4_16D]` when the first consumer
7393
// (planner strategy selection) needs it; keep the read surface minimal until then.
@@ -232,6 +252,17 @@ mod tests {
232252
assert_eq!(soa.w_slot(), 7);
233253
}
234254

255+
#[test]
256+
fn row_for_local_key_defaults_to_none_until_a_key_index_is_materialized() {
257+
// Deferred-binding default: a view with no per-row key column resolves
258+
// every local_key to None — the consumer falls back to the positional
259+
// (mailbox_id, row) address, never a wrong row. The Backend::MailboxSoa
260+
// router can name this baton; an owner that stores keys overrides it.
261+
let soa = sample();
262+
assert_eq!(soa.row_for_local_key(0), None);
263+
assert_eq!(soa.row_for_local_key(u64::MAX), None);
264+
}
265+
235266
#[test]
236267
fn owner_advances_phase_and_sets_libet_anchor() {
237268
let mut soa = sample();

0 commit comments

Comments
 (0)