feat(contract): facet::CascadeShape view-rotations + ClassArm classid switch#621
Conversation
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>
|
Warning Review limit reached
Next review available in: 5 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the 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 configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (6)
📝 WalkthroughWalkthroughAdds cascade-ladder APIs and invariants to ChangesFacet Cascade Algebra
Rust 1.95 Toolchain Pins
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
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. Comment |
There was a problem hiding this comment.
💡 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".
…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>
There was a problem hiding this comment.
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
📒 Files selected for processing (5)
.claude/board/LATEST_STATE.mdcrates/bge-m3/rust-toolchain.tomlcrates/lance-graph-contract/src/facet.rscrates/reader-lm/rust-toolchain.tomlpython/rust-toolchain.toml
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>
Pins + implements the cascade carving arithmetic (the OGAR substrate §1.5 flagged it as "to pin against
FacetCascadebefore coding"). Revised per operator review — two corrections folded in:The algebra (
lance-graph-contract::facet, zero-depconst fn)CASCADE_UNITS = 12— the facet's6×2tier-bytes ≡ a 12-field class's fields. Unit-agnostic: the same index math addresses facet bytes and class fields.CascadeShape::{G6D2, G4D3, G3D4}carve the 12-unit ladder asG 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_ofis 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).G4D3is the WORST CASE, not a co-equal carving (operator: "4 group_of is a very bad and unwanted example"). It straddles tier boundaries →group_ofmust divide →is_byte_aligned()isfalse,shift()isNone. Excluded fromALIGNED; kept inROTATIONSonly as the deliberate rare escape-hatch rotation. (Replaces the original co-equalALL.)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/KausalSpecon the resolved node), reached by switching the classid toFunctions; carvings address the THINK/Viewarm only. (OGAR THINK/DO split.) A straddling carve to "get to" a function is exactly the worst caseG4D3warns 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
cascade_rotations_are_total_but_only_aligned_are_defaults(G·D totality, index∘(group,level) round-trip, shift-vs-divide,ALIGNEDexcludes /ROTATIONSincludesG4D3),classid_switch_separates_view_from_functions, plus the grouping + per-group-LCP tests. + 3 compile-timeG·D == CASCADE_UNITSasserts.clippy --lib-D warningsclean +rustfmtclean. Probe-workspace verified offline (the full workspace'sndarraygit dep is 403 offline).Board hygiene
.claude/board/LATEST_STATE.mdContract 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