@@ -87,38 +87,49 @@ facet, baked into the binary. Three properties:
8787
8888### a. One ClassView * rotates* the facet layout — no "versions"
8989
90- The 16-byte facet's tier payload is not locked to a single carving. A ClassView
91- can ** always rotate** — read the SAME 12 cascade bytes under a different
92- grouping — to fit the class. The carvings (pinned as
93- ` lance_graph_contract::facet::CascadeShape ` , ` CascadeShape::ROTATIONS ` ):
90+ The 16-byte facet's tier payload is not locked to a single carving. The shape is
91+ ** class-conditioned** — * mapped from the class's inherited format and selected by
92+ ` classid ` * (the filter), never restated or locked (operator veto 2026-06-29). A
93+ ClassView can also ** rotate** — read the SAME 12 cascade bytes under a different
94+ grouping. The shapes (pinned as ` lance_graph_contract::facet::CascadeShape ` ,
95+ ` CascadeShape::from_levels(d) ` ):
9496
9597```
96- 6× (1:2) ALIGNED default — 6 tiers, each a 1:2 hierarchy (group_of = i >> 1, a shift)
97- 3 × (1:2:3:4 ) ALIGNED default — 3 tier-pairs , each 1:2:3:4 (group_of = i >> 2 , a shift )
98- 4 × (1:2:3) WORST CASE — straddles tier boundaries (group_of = i / 3 , a DIVIDE )
98+ 6× (1:2) Rails — 6 tiers, each a 1:2 hierarchy (group_of = i >> 1, a shift)
99+ 4 × (1:2:3) other frameworks — 4 tier-groups , each 1:2:3 (group_of = i / 3 , a divide )
100+ 3 × (1:2:3:4 ) canonical GUID — 3 tier-pairs, each 1:2:3:4 (group_of = i >> 2 , a shift )
99101```
100102
101- ** Only the byte-aligned carvings are defaults.** ` 6×(1:2) ` and ` 3×(1:2:3:4) `
102- keep ` group_of ` a pure shift (the canon's "tier-of-level is a shift, never a
103- branch"). ** ` 4×(1:2:3) ` is the worst case, not a co-equal carving** — it
104- straddles tier boundaries so ` group_of ` must DIVIDE (` CascadeShape::is_byte_aligned() `
105- is ` false ` , ` shift() ` is ` None ` ). It is * prevented on the common path* and kept
106- only as the ** rare rotation / escape hatch** : a ClassView may rotate to it
107- deliberately when a rare class (some Odoo models) needs to relieve
108- ** classid-stacking entropy** — rotate the reading rather than mint another
109- classid. So there is ** no need for hardcoded facet "versions" (V1/V2/V3)** — one
110- compiled ClassView subsumes the rotation set; the straddle stays legal only as a
111- deliberate, rare rotation. Hardcoding a format per version is the thing to
112- * delete* .
113-
114- > ** Carvings address the VIEW, never the functions.** A rotation re-reads the
115- > data layout; it does NOT reach behaviour. Functions are encoded by the
103+ ** The shape follows the class, not a global lock** (operator: "Rails might need
104+ 6x2x8bit, others 4x3x8bit"). The depth ` D ∈ {2,3,4} ` is a per-class constant the
105+ ` classid ` resolves (` CascadeShape::from_levels ` ). ` 6×2 ` /` 3×4 ` carve on tier
106+ boundaries so ` group_of ` is a pure shift (the canon's "tier-of-level is a shift,
107+ never a branch"); ** ` 4×3 ` is legitimate for the frameworks that need it** — its
108+ ` group_of ` divides (` is_byte_aligned() ` is ` false ` ), the per-class * cost* a class
109+ opts into, ** not a prohibition** . So there is ** no need for hardcoded facet
110+ "versions" (V1/V2/V3)** — one compiled ClassView reads whichever shape the
111+ classid selects. Hardcoding a format per version (or locking a single shape) is
112+ the thing to * delete* .
113+
114+ > ** Carvings address the VIEW, never the functions.** A shape/rotation re-reads
115+ > the data layout; it does NOT reach behaviour. Functions are encoded by the
116116> ** classid acting as an additional switch** — ` lance_graph_contract::facet::ClassArm `
117117> ` { View, Functions } ` , the OGAR THINK/DO split (` OGAR-AST-CONTRACT.md ` ).
118118> Reaching a function = switch the classid to the ` Functions ` arm (the
119119> ` ActionDef ` /` KausalSpec ` on the resolved Core node), * never* slice the
120- > tier-bytes. A straddling carve to "get to" a function is exactly the worst
121- > case the ` 4×(1:2:3) ` example warns against.
120+ > tier-bytes — that is the genuine mistake (a straddle used to "get to" a
121+ > function), distinct from a class whose * data layout* legitimately needs ` 4×3 ` .
122+
123+ ** Out of transpile scope — the ` G2×48bit ` encoding lane.** The byte-shaped
124+ shapes above (` 6×2 ` /` 4×3 ` /` 3×4 ` , 8-bit tiers) are the * transpile / ClassView
125+ field-grouping* lane. A ** separate** lane reads the same facet bytes at
126+ ` G2×48bit ` granularity — the two 48-bit chains (` FacetCascade::hi_chain ` /
127+ ` lo_chain ` , cf. the CAM-PQ ` 6×256 ` path code) — for ** helix** (location encoding;
128+ q2 / helix) and ** CAM-PQ** (centroid encoding; lance-graph / DeepNSM). These are
129+ ** not required by transpile** and must not be dragged into ClassView shape
130+ selection (operator 2026-06-29). The DeepNSM ** COCA** 4096-word English-vocabulary
131+ CAM index codebook is a likely future ` G2×48bit ` consumer — it may * earn its
132+ keep* there, but it is not a transpile dependency.
122133
123134### b. Sub-range mapping + nested ClassViews stacked into constructors
124135
@@ -172,16 +183,19 @@ case.)
172183> ` lance_graph_contract::facet::CascadeShape ` (` G6D2 ` / ` G4D3 ` / ` G3D4 ` ,
173184> ` G·D = CASCADE_UNITS = 12 ` ) over ` FacetCascade::tier_bytes() ` — `index(g,l) =
174185> g·D + l` , ` group_of` / ` level_of` inverses, ` cascade_byte`, per-group LCP
175- > ` cascade_group_shared ` . ` CascadeShape::ALIGNED = [G3D4, G6D2] ` are the
176- > shift-` group_of ` ** defaults** (` shift() ` is ` Some ` ); ` CascadeShape::ROTATIONS `
177- > is the full rotation set a ClassView may rotate through. ** ` G4D3 ` is the worst
178- > case** — ` is_byte_aligned() ` is ` false ` , ` shift() ` is ` None ` , ` group_of `
179- > divides — excluded from ` ALIGNED ` , kept in ` ROTATIONS ` only as the rare
180- > escape-hatch rotation (classid-stacking-entropy relief). ** Functions are NOT a
181- > carving** — ` facet::ClassArm { View, Functions } ` is the classid's additional
182- > THINK/DO switch; carvings address ` View ` only. Zero-dep, ` const fn ` ,
183- > probe-verified (lance-graph #621 ). One algebra for both the facet bytes and a
184- > 12-field class — the shared substrate the three language SDKs (§1.6) all read.
186+ > ` cascade_group_shared ` . The shape is ** class-conditioned** , selected by the
187+ > ` classid ` from the inherited format via ` CascadeShape::from_levels(d) ` —
188+ > ` 2 → G6D2 ` (Rails), ` 3 → G4D3 ` (other frameworks), ` 4 → G3D4 ` (the GUID
189+ > default); ` CascadeShape::ALIGNED = [G3D4, G6D2] ` are the shift-` group_of ` shapes
190+ > and ` ROTATIONS ` the full set. ** ` G4D3 ` (` 4×3 ` ) is legitimate per-class, not a
191+ > "worst case to prevent"** (operator veto 2026-06-29): its ` group_of ` divides
192+ > (` is_byte_aligned() ` is ` false ` ) — a per-class * cost* , not a prohibition;
193+ > ` is_byte_aligned ` /` shift ` /` ALIGNED ` distinguish the shift fast-path from the
194+ > divide shape, never a reject gate. ** Functions are NOT a carving** —
195+ > ` facet::ClassArm { View, Functions } ` is the classid's additional THINK/DO
196+ > switch; carvings address ` View ` only. Zero-dep, ` const fn ` , probe-verified
197+ > (lance-graph #621 ). One algebra for both the facet bytes and a 12-field class —
198+ > the shared substrate the three language SDKs (§1.6) all read.
185199
186200---
187201
@@ -310,6 +324,21 @@ A node is `key(128/GUID) + value`. Lance may compress the value arbitrarily
310324(columnar, dictionary, PQ); the key is never compressed and never needs the
311325value decoded to route. (Canon: "THE GUID IS THE KEY OF KEY-VALUE.")
312326
327+ ** Two doctrines for the consumer model (operator 2026-06-29), neither a blocker:**
328+
329+ - ** Clean ⇒ expansion is ` classid ` -inherited.** A clean class can grow its field
330+ set / capacity; the ` classid ` selects the expanded shape — no global change.
331+ Expansion is never a transpile blocker (cf. the class-conditioned ` CascadeShape `
332+ / "don't lock the shape").
333+ - ** Bulk raw data → a * separate* table, not the SoA value.** The 480-byte value
334+ is for structured/compressible columns; a raw payload that won't fit even
335+ compressed (a ~ 3.2 Gbp genome; the FMA / BodyParts3D anatomy mesh at ** 4M
336+ vertices / 6M triangles** ) lives in its own Lance table, referenced by
337+ ` key ` /` classid ` — out-of-line, addressed not inlined, and still not a blocker
338+ (the anatomy mesh ** baked cleanly as a SoA release** ). Transpile mints the
339+ * structured* class; the bulk payload is a table reference, not a transpile
340+ dependency.
341+
313342---
314343
315344## 3. The 85 / 15 split (the consumer model)
0 commit comments