Skip to content

feat(contract): facet::CascadeShape view-rotations + ClassArm classid switch#621

Merged
AdaWorldAPI merged 8 commits into
mainfrom
claude/odoo-rs-transcode-lf8ya5
Jun 29, 2026
Merged

feat(contract): facet::CascadeShape view-rotations + ClassArm classid switch#621
AdaWorldAPI merged 8 commits into
mainfrom
claude/odoo-rs-transcode-lf8ya5

Conversation

@AdaWorldAPI

@AdaWorldAPI AdaWorldAPI commented Jun 29, 2026

Copy link
Copy Markdown
Owner

Pins + implements the cascade carving arithmetic (the OGAR substrate §1.5 flagged it as "to pin against FacetCascade before coding"). Revised per operator review — two corrections folded in:

The algebra (lance-graph-contract::facet, zero-dep const fn)

  • CASCADE_UNITS = 12 — the facet's 6×2 tier-bytes ≡ a 12-field class's fields. Unit-agnostic: the same index math addresses facet bytes and class fields.
  • Carvings are VIEW rotations. CascadeShape::{G6D2, G4D3, G3D4} carve the 12-unit ladder as G groups × D levels, G·D = 12. A ClassView can always rotate — read the same bytes under a different carving — per class.
    • CascadeShape::ALIGNED = [G3D4, G6D2] — the byte-aligned defaults; group_of is a pure shift (shift()Some(2)/Some(1)), the canon's "tier-of-level is a shift, never a branch".
    • CascadeShape::ROTATIONS = [G3D4, G4D3, G6D2] — the full rotation set a ClassView may rotate through; the relief valve for classid-stacking entropy (rare, e.g. some Odoo classes — rotate instead of minting another classid).
  • G4D3 is the WORST CASE, not a co-equal carving (operator: "4 group_of is a very bad and unwanted example"). It straddles tier boundaries → group_of must divideis_byte_aligned() is false, shift() is None. Excluded from ALIGNED; kept in ROTATIONS only as the deliberate rare escape-hatch rotation. (Replaces the original co-equal ALL.)
  • ClassArm::{View, Functions} — the classid is an additional switch (operator: "functions should be encoded using the Classid as an additional switch (functions, view)"). Functions are not a facet carving — they are the DO arm (ActionDef/KausalSpec on the resolved node), reached by switching the classid to Functions; carvings address the THINK/View arm only. (OGAR THINK/DO split.) A straddling carve to "get to" a function is exactly the worst case G4D3 warns against.
  • FacetCascade::tier_bytes() (12-byte coarse→fine ladder), cascade_byte(shape,g,l), cascade_group_shared(other,shape,g) (per-group LCP).

Test Plan

  • 8/8 lib facet tests green. New/updated: cascade_rotations_are_total_but_only_aligned_are_defaults (G·D totality, index∘(group,level) round-trip, shift-vs-divide, ALIGNED excludes / ROTATIONS includes G4D3), classid_switch_separates_view_from_functions, plus the grouping + per-group-LCP tests. + 3 compile-time G·D == CASCADE_UNITS asserts.
  • clippy --lib -D warnings clean + rustfmt clean. Probe-workspace verified offline (the full workspace's ndarray git dep is 403 offline).

Board hygiene

.claude/board/LATEST_STATE.md Contract Inventory updated in the same commits.

Companion: OGAR #138 (substrate §1.5/§1.6 doc + the C#/Python SDK codegen that reads this algebra).

🤖 Generated with Claude Code

https://claude.ai/code

Summary by CodeRabbit

  • New Features
    • Added improved facet cascade handling that exposes tiered byte “ladder” mapping with explicit group/level addressing and shape-aware alignment.
    • Introduced an explicit split between view-oriented and function-oriented behavior during facet resolution.
  • Tests
    • Expanded coverage for cascade shape rotations, alignment edge cases, ladder layout, per-group shared-prefix behavior, and invariants.
  • Documentation
    • Updated an append-only design note describing the cascade algebra and alignment doctrine.
  • Chores
    • Pinned Rust toolchains to 1.95 across affected crates for consistency.

claude added 2 commits June 28, 2026 22:12
python/, crates/bge-m3/, and crates/reader-lm/ still pinned channel 1.94.0 while the root rust-toolchain.toml (and bge-m3/reader-lm's own Cargo.toml rust-version) are already 1.95. Align all three to the ecosystem-wide 1.95 pin.

Co-Authored-By: Claude <noreply@anthropic.com>
…ings

Add the G×D=12 cascade carving algebra to lance-graph-contract::facet, the
shared substrate the compiled-ClassView spine and the per-language SDKs read.

- CascadeShape {G6D2, G4D3, G3D4}: carve the 12 cascade units as G groups ×
  D levels, G·D = CASCADE_UNITS = 12 always. groups()/levels(), index(g,l) =
  g·D+l, inverses group_of/level_of (G3D4/G6D2 group_of is a shift — the canon
  'tier-of-level is a shift, never a branch'; G4D3 is the straddle that divides).
- FacetCascade::tier_bytes() exposes the 12 cascade bytes as one coarse→fine
  ladder (hi then lo per tier); cascade_byte(shape,g,l) reads one unit;
  cascade_group_shared(other,shape,g) is the per-group coarse→fine LCP redout.
- Unit-agnostic: the same index math addresses the facet bytes AND a 12-field
  class — the OGAR GUID 3×4-vs-4×3 debate generalised from nibbles to bytes.

Zero-dep const fn; +3 tests + 3 compile-time G·D asserts; lib facet 7/7 green,
clippy -D warnings clean (probe-workspace verified offline).

Board hygiene: LATEST_STATE.md Contract Inventory updated in the same commit.

Co-Authored-By: Claude <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@AdaWorldAPI, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 5 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 18b0098a-ca33-41f5-a55a-fe9d68b8b50e

📥 Commits

Reviewing files that changed from the base of the PR and between 0b6004d and 64a0d2c.

📒 Files selected for processing (6)
  • .claude/board/LATEST_STATE.md
  • crates/bge-m3/rust-toolchain.toml
  • crates/lance-graph-contract/src/canonical_node.rs
  • crates/lance-graph-contract/src/facet.rs
  • crates/reader-lm/rust-toolchain.toml
  • python/rust-toolchain.toml
📝 Walkthrough

Walkthrough

Adds cascade-ladder APIs and invariants to lance-graph-contract::facet, documents the related node-slot sizing rule in the board state, and pins three Rust toolchain files to 1.95 with comments. The PR also adds unit tests covering the new facet behavior.

Changes

Facet Cascade Algebra

Layer / File(s) Summary
Cascade contracts and node-slot doctrine
crates/lance-graph-contract/src/facet.rs, crates/lance-graph-contract/src/canonical_node.rs
Defines CASCADE_UNITS, CascadeShape, and ClassArm, plus GUIDS_PER_NODE with compile-time assertions that fix the cascade and node-row sizing rules.
FacetCascade helpers and tests
crates/lance-graph-contract/src/facet.rs, crates/lance-graph-contract/src/canonical_node.rs
Adds tier_bytes, cascade_byte, and cascade_group_shared, then validates cascade rotation, alignment, class-arm separation, ladder indexing, shared-prefix behavior, and the node-slot breakdown in unit tests.
Board documentation update
.claude/board/LATEST_STATE.md
Records the new cascade-shape, class-arm, FacetCascade helper, and node-slot doctrine entries in the board state document.

Rust 1.95 Toolchain Pins

Layer / File(s) Summary
Toolchain channel update
crates/bge-m3/rust-toolchain.toml, crates/reader-lm/rust-toolchain.toml, python/rust-toolchain.toml
Changes the Rust channel from 1.94.0 to 1.95 in three toolchain files and adds alignment comments.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • AdaWorldAPI/lance-graph#489: Builds on the fixed NodeRow sizing in canonical_node.rs, which this PR extends with GUIDS_PER_NODE and a sizing invariant.
  • AdaWorldAPI/lance-graph#614: Introduced the FacetCascade structure in lance-graph-contract::facet, which this PR extends with cascade-shape and byte-ladder helpers.

Poem

🐇 I hop through tiers of bytes at dawn,
With view and functions neatly drawn.
Twelve little slots in rows of light,
And 1.95 keeps the burrow right.
Cascade wheels go clickety-skip,
A tidy facet on the rabbit’s trip.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly reflects the main change: new CascadeShape rotation logic and the ClassArm classid split in the contract crate.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cd6160d26c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/bge-m3/rust-toolchain.toml Outdated
…view #621)

Address operator review on #621:

1. G4D3 (the divide/straddle) is the WORST CASE, not a co-equal carving.
   Carvings are VIEW rotations of the 12-unit ladder:
   - CascadeShape::ALIGNED = [G3D4, G6D2] — byte-aligned defaults; group_of is
     a pure SHIFT (canon 'tier-of-level is a shift, never a branch'). New
     shift() -> Option<u32> returns Some(2)/Some(1); is_byte_aligned() == true.
   - CascadeShape::ROTATIONS = [G3D4, G4D3, G6D2] — the full rotation set a
     ClassView may rotate through. A ClassView can ALWAYS rotate (read the same
     bytes under a different carving) per class — the relief valve for
     classid-stacking entropy (rare, e.g. some Odoo classes: rotate instead of
     minting another classid).
   - G4D3: shift() == None, is_byte_aligned() == false, group_of DIVIDES —
     excluded from ALIGNED, kept in ROTATIONS only as the deliberate rare
     escape hatch. (replaces the old co-equal ALL constant.)

2. Functions are NOT a facet carving. New ClassArm { View, Functions } — the
   classid is an additional THINK/DO switch (OGAR-AST-CONTRACT). Behaviour is
   reached by switching the classid to the Functions arm (ActionDef/KausalSpec
   on the resolved node); carvings address the View arm only. A straddling
   carve to 'get to' a function is exactly the worst case G4D3 warns against.

+4 facet tests (cascade_rotations_are_total_but_only_aligned_are_defaults,
classid_switch_separates_view_from_functions, + updated grouping/LCP tests);
8/8 lib facet green, clippy -D warnings + rustfmt clean (probe-verified offline).

Board: LATEST_STATE.md Contract Inventory entry updated in the same commit.

Co-Authored-By: Claude <noreply@anthropic.com>
@AdaWorldAPI AdaWorldAPI changed the title feat(contract): facet::CascadeShape — one cascade algebra, three carvings feat(contract): facet::CascadeShape view-rotations + ClassArm classid switch Jun 29, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/lance-graph-contract/src/facet.rs`:
- Around line 441-462: `CascadeShape::index`, `group_of`, and `level_of`
currently assume inputs are already in range, so `u8` arithmetic can wrap before
widening and the inverse mapping only holds for valid cascade units. Add an
explicit bounds check or debug assertion in these methods (or document the
precondition on the public API) so callers cannot pass out-of-range `group`,
`level`, or `unit` values and silently get the wrong slot/index.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: eaad7a69-40f5-4b1c-bbc6-410086afd583

📥 Commits

Reviewing files that changed from the base of the PR and between 1804762 and 18286a0.

📒 Files selected for processing (5)
  • .claude/board/LATEST_STATE.md
  • crates/bge-m3/rust-toolchain.toml
  • crates/lance-graph-contract/src/facet.rs
  • crates/reader-lm/rust-toolchain.toml
  • python/rust-toolchain.toml

Comment thread crates/lance-graph-contract/src/facet.rs
claude added 5 commits June 29, 2026 20:37
Operator principle (2026-06-29): the 4096-bit / 512-byte SoA node is 32 ×
16-byte GUID-sized slots, so in the worst case you Tetris what you need across
slots — preference clean / SoC over packed.

- canonical_node::GUIDS_PER_NODE = NODE_ROW_STRIDE / 16 = 32 (compile-time
  asserted == 32 && ·size_of::<NodeGuid>() == NODE_ROW_STRIDE). key + edges
  occupy 2 slots; the 480-byte value slab is the remaining 30 to lay a class's
  concerns into. Doc states the doctrine: give each concern its own 16-byte
  slot rather than bit-pack two into one; the 32-slot capacity is why the
  CascadeShape::G4D3 straddle (packing) is almost never needed, and the headroom
  behind 'rotate / spread to a fresh slot instead of minting another classid'.
- facet::CascadeShape G4D3 doc cross-refs GUIDS_PER_NODE (SoC over packed).
- test guids_per_node_is_32_slots_clean_soc_over_packed (asserts the 2+30 split).

Lib facet 8/8 + canonical_node 43/43 green; clippy -D warnings + rustfmt clean
(probe-verified offline). Board: LATEST_STATE.md entry updated same commit.

Co-Authored-By: Claude <noreply@anthropic.com>
…from_levels

Operator small veto (2026-06-29): the shape is mapped from the class's INHERITED
format and selected by classid — it shouldn't be restated or LOCKED. 'Quadruplet'
was a misread; the shapes are the per-class CascadeShape: Rails 6×2, other
frameworks 4×3, the GUID 3×4 (all G·D=12, 8-bit tiers). So 4×3 is legitimate
per-class, NOT a 'worst case to prevent'.

- Recast all CascadeShape docs from 'G4D3 worst case / prevent / rare escape
  hatch' → class-conditioned: Rails→G6D2, other frameworks→G4D3, GUID→G3D4. The
  divide group_of of G4D3 is a per-class shape COST a class opts into, not a
  prohibition; is_byte_aligned()/shift()/ALIGNED now read as 'shift fast-path vs
  divide shape', not a reject gate.
- NEW CascadeShape::from_levels(d) — the class-conditioned D∈{2,3,4} selector
  (2→G6D2, 3→G4D3, 4→G3D4), inverse of levels(); the classid resolves D, never a
  global lock. Handles 'if one of the 2-4 becomes a constant dependent on class
  condition'.
- canonical_node GUIDS_PER_NODE doctrine reworded: 'don't mix distinct concerns
  in one facet' (independent of shape); the per-class 6×2/4×3/3×4 shape is a
  separate, class-conditioned choice (a 4×3 class is clean).
- Test renamed cascade_shapes_are_total_and_class_conditioned (+ from_levels
  round-trip). Facet 7/7 + canonical_node 43/43 green, clippy + rustfmt clean.

Board: LATEST_STATE.md correction line appended (append-only).

Co-Authored-By: Claude <noreply@anthropic.com>
…-PQ lane

Operator scoping (2026-06-29): helix + CAM-PQ are a separate G2×48bit encoding
lane (the two 48-bit chains / CAM-PQ 6×256 path code) for location (helix) and
centroid (CAM-PQ, DeepNSM) — NOT required by transpile. Note on CascadeShape that
the byte-shapes are the transpile/ClassView field-grouping lane; the G2×48bit
two-chain view (hi_chain/lo_chain) is the helix/CAM-PQ location/centroid lane,
never dragged into shape selection. Doc-only.

Co-Authored-By: Claude <noreply@anthropic.com>
…xpansion

Operator doctrines (2026-06-29), neither a blocker:
1. Clean => expansion is classid-inherited (no global layout change; cf.
   RESERVE-DON'T-RECLAIM + class-conditioned CascadeShape).
2. Bulk raw data lives out-of-line in a SEPARATE Lance table, not the 480-byte
   value slab — a payload that won't fit even compressed (~3.2 Gbp genome; the
   FMA/BodyParts3D anatomy mesh at 4M vertices/6M triangles) is referenced by
   key/classid, addressed not inlined. Still not a blocker — the anatomy mesh
   baked cleanly as a SoA release. Node stays 512 B. Doc-only.

Co-Authored-By: Claude <noreply@anthropic.com>
…toolchains

Address the two actionable PR-review findings on #621:

- CodeRabbit (Major), facet.rs: CascadeShape::index/group_of/level_of did u8
  arithmetic before widening, so out-of-range group/level/unit could wrap and
  the inverse only held for unit < CASCADE_UNITS. index now widens to usize
  BEFORE multiply/add (no u8 wrap possible), and all three carry a debug_assert
  precondition + a documented precondition (group<groups, level<levels,
  unit<CASCADE_UNITS). Valid-range behaviour unchanged; facet 7/7 green.
- Codex (P2), rust-toolchain.toml x3 (bge-m3, reader-lm, python): channel was
  floating "1.95" (a distinct channel name from the root's exact "1.95.0"),
  so building from those subdirs tried to sync channel-rust-1.95 instead of the
  installed root toolchain — breaking offline/provisioned setups. Pinned to
  exact "1.95.0" to match the root.

clippy -D warnings + rustfmt clean (probe-verified offline).

Co-Authored-By: Claude <noreply@anthropic.com>
@AdaWorldAPI AdaWorldAPI merged commit c30742e into main Jun 29, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants