feat(experimental): reusable RankQuant bucket-code API (#220)#226
Conversation
Port ordgraph-proto/src/code.rs into ordvec as an index-free bucket-code surface
so downstream evidence systems consume declared codes instead of forking kernel
math. experimental-gated.
API (ordvec::{CompositionSpec, RankQuantSpec, BucketCode, CompositionViolation}):
- CompositionSpec: fixed-composition validation (dim/buckets, expected_per_bucket,
histogram, validate_codes).
- RankQuantSpec: dim+bits in {1,2,4}.
- BucketCode: new(spec, codes) validated; from_ranks; from_vector(dim, bits, &[f32])
— the new ordvec-primitive path (rank_transform + rank_to_bucket), output feeds
Contingency::new (#219); top_bitmap.
- CompositionViolation: structured error enum (Display + Error).
Rank math not duplicated (delegates to crate::rank). Parity tests reproduce the
proto's exact assertion values; +validation + from_vector<->contingency cross-check.
Verified: fmt/clippy(-D warnings, experimental+default)/test (69 lib + 2 integration,
default-build gating confirmed) green. No new deps. Refs #220.
Signed-off-by: Nelson Spence <nelson@projectnavi.ai>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Code Review by Qodo
Context used 1.
|
PR Summary by QodoAdd experimental index-free RankQuant BucketCode API with validation WalkthroughsDescription• Introduce experimental BucketCode API to derive validated fixed-composition bucket ids. • Delegate rank math to existing rank primitives; add structured CompositionViolation errors. • Add parity and integration tests, including Contingency contract cross-check. Diagramgraph TD
A["Downstream caller"] --> B["ordvec::BucketCode"] --> C["crate::rank"]
B --> D["CompositionSpec / RankQuantSpec"]
B --> E["Contingency::new (from #219)"]
F["Tests"] --> B
High-Level AssessmentThe following are alternative approaches to this PR: 1. Reuse existing OrdvecError for bucket-code failures
2. Expose a fallible-from-vector API that returns raw Vec + separate validate()
3. Allow bits=8 in RankQuantSpec now (match proto) and gate packed-format support later
Recommendation: The PR’s approach (feature-gated, index-free BucketCode that delegates rank math to crate::rank and enforces fixed-composition invariants) is directionally strong and minimizes duplication. The two key maintainer decisions to settle before stabilizing are (1) whether CompositionViolation remains a distinct public error type versus being folded into OrdvecError, and (2) whether bits=8 should be accepted now for API continuity or intentionally excluded to reflect the current packed RankQuant domain. File ChangesEnhancement (1)
Tests (1)
Other (1)
|
There was a problem hiding this comment.
Code Review
This pull request introduces the bucket_code module under the experimental feature flag, which implements index-free, fixed-composition ordinal bucket codes. It includes the CompositionSpec, RankQuantSpec, and BucketCode structures, along with comprehensive unit and integration tests. The review feedback identifies two key issues: first, CompositionSpec::new should reject buckets > 256 to prevent silent truncation when casting bucket IDs to u8; second, the calculation rank * buckets in from_ranks should cast operands to u128 to prevent integer overflow.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
|
/agentic_review |
|
Code review by qodo was updated up to the latest commit 5af8411 |
…226) - CompositionSpec::new now rejects buckets>256 (InvalidSpec) — codes are u8, so >256 would silently truncate a computed id via 'as u8' and fail later with a misleading WrongBucketCount. - from_ranks computes rank*buckets in u64 to avoid usize overflow on 32-bit/ wasm32 for large dim (matches util.rs checked-math discipline). - Tests: >256-buckets rejection + boundary; from_vector unsupported-bits path. Signed-off-by: Nelson Spence <nelson@projectnavi.ai>
qodo: the PR added the bucket-code surface without explicit migration steps for deleting ordgraph-proto's local CompositionSpec/RankQuantSpec/BucketCode fork. Add a 'Migration from ordgraph-proto' subsection: the drop-in import + delete src/code.rs steps, the rank-math-delegation note, and the two intentional deviations (bits=8 deferred to #221, buckets<=256). Signed-off-by: Nelson Spence <nelson@projectnavi.ai>
|
/agentic_review |
|
Code review by qodo was updated up to the latest commit fd1efe8 |
|
On the parity-test finding — deliberate, documented deferral. This finding asks for a test asserting parity against an external prototype implementation that is not yet a published or git-reachable dependency of this crate. We are intentionally not adding that test in this PR:
The |
Add a focused test `rankquant_spec_rejects_bits_8` that asserts both
`RankQuantSpec::new(8, 8)` and `BucketCode::from_vector(8, 8, &v)`
return `CompositionViolation::InvalidBits { bits: 8 }`, pinning the
deliberate b=8 exclusion so the boundary cannot regress silently.
Addresses the qodo finding: "bits=8 behavior untested" (PR #226).
Signed-off-by: Nelson Spence <nelson@projectnavi.ai>
…e references) Replace the "Migration from ordgraph-proto" rustdoc section with a self-contained "Adopting this API" adoption note describing how external callers can replace local forks with the ordvec types. Rename the "ordgraph bucket-code parity gate" test block comment to "bucket-code behavioral contract", describing the invariants under test rather than a migration relationship. No production behaviour, test logic, or assert values changed. Signed-off-by: Nelson Spence <nelson@projectnavi.ai>
|
/agentic_review |
|
Code review by qodo was updated up to the latest commit 1c8d5ab |
…-code Signed-off-by: Nelson Spence <nelson@projectnavi.ai> # Conflicts: # src/lib.rs
…erge) The cross-API integration test stood in a local re-implementation of `Contingency::new`'s histogram + `diagonal_agreement` because the contingency module was not yet in this branch's tree (it shipped via the sibling #219 work). Now that the contingency surface is merged in, do the mechanical swap the test's own doc anticipated: drop the reference re-implementation and assert directly against the real `Contingency::new(..).diagonal_agreement()`. Same acceptance property (#220 ⇄ #219): from_vector output is a valid, balanced contingency input. Both cases pass. Signed-off-by: Nelson Spence <nelson@projectnavi.ai>
… helpers (#222) (#227) * feat(experimental): reusable RankQuant bucket-code API (#220) Port ordgraph-proto/src/code.rs into ordvec as an index-free bucket-code surface so downstream evidence systems consume declared codes instead of forking kernel math. experimental-gated. API (ordvec::{CompositionSpec, RankQuantSpec, BucketCode, CompositionViolation}): - CompositionSpec: fixed-composition validation (dim/buckets, expected_per_bucket, histogram, validate_codes). - RankQuantSpec: dim+bits in {1,2,4}. - BucketCode: new(spec, codes) validated; from_ranks; from_vector(dim, bits, &[f32]) — the new ordvec-primitive path (rank_transform + rank_to_bucket), output feeds Contingency::new (#219); top_bitmap. - CompositionViolation: structured error enum (Display + Error). Rank math not duplicated (delegates to crate::rank). Parity tests reproduce the proto's exact assertion values; +validation + from_vector<->contingency cross-check. Verified: fmt/clippy(-D warnings, experimental+default)/test (69 lib + 2 integration, default-build gating confirmed) green. No new deps. Refs #220. Signed-off-by: Nelson Spence <nelson@projectnavi.ai> * feat(experimental): constant-weight bitmap overlap + finite null-tail helpers (#222) Port ordgraph-proto/src/bitmap.rs into ordvec (stacked on #220 BucketCode), experimental-gated. The ordinal-bitmap overlap + finite-null surface downstream evidence systems consume. ordvec::{ConstantWeightBitmap, PackedConstantWeightBitmap, BitmapNull, top_group_overlap_vector, choose}: - ConstantWeightBitmap::from_top_bucket(&BucketCode) + overlap (reference path). - PackedConstantWeightBitmap::from_bucket_range/from_top_group; overlap routes through crate::util::and_popcount (the production popcount-AND primitive, not a hand-rolled loop). - BitmapNull: space_size=C(dim,w), fiber_count(o)=C(w,o)*C(dim-w,w-o), tail_count(threshold)=Σ_{o>=threshold} fiber_count(o); upper-tail = tail/space. - choose: u128 binomial. Parity: reproduces proto assertion values; fiber-partition identity (Σ fiber_count == space_size) verified for 7 (dim,weight); overlap parity (bool == packed == naive); choose vs known binomials + symmetry. No new deps; zero unsafe. Verified: fmt/clippy(-D warnings, exp+default)/test(exp+default gating)/MSRV 1.89 green. Refs #222. Signed-off-by: Nelson Spence <nelson@projectnavi.ai> * fix(bucket_code): bound buckets<=256 + u64 bucket math (gemini/qodo) (#226) - CompositionSpec::new now rejects buckets>256 (InvalidSpec) — codes are u8, so >256 would silently truncate a computed id via 'as u8' and fail later with a misleading WrongBucketCount. - from_ranks computes rank*buckets in u64 to avoid usize overflow on 32-bit/ wasm32 for large dim (matches util.rs checked-math discipline). - Tests: >256-buckets rejection + boundary; from_vector unsupported-bits path. Signed-off-by: Nelson Spence <nelson@projectnavi.ai> * fix(const_weight_bitmap): fail-loud overflow in choose/fiber_count (gemini/qodo) (#222) Resolves the flagged u128-overflow decision in the safe direction (the bots and the maintainer both wanted fail-loud before stable): - choose(): gcd-cancellation of each (n-i)/(i+1) factor (extends the representable range to the full set of C(n,k) that fit u128) + checked_mul, so a true overflow PANICS (both debug and release) instead of silently wrapping to a wrong count. - fiber_count(): checked_mul on the two binomials. - Overflow docs updated (deliberate divergence from the proto's wrap-in-release). - Tests: range-extension via Pascal's identity (C(128,64)); should_panic on C(300,150) overflow. Signed-off-by: Nelson Spence <nelson@projectnavi.ai> * docs(bucket_code): add ordgraph-proto migration note (qodo) (#220) qodo: the PR added the bucket-code surface without explicit migration steps for deleting ordgraph-proto's local CompositionSpec/RankQuantSpec/BucketCode fork. Add a 'Migration from ordgraph-proto' subsection: the drop-in import + delete src/code.rs steps, the rank-math-delegation note, and the two intentional deviations (bits=8 deferred to #221, buckets<=256). Signed-off-by: Nelson Spence <nelson@projectnavi.ai> * test: pin bits=8 rejection for RankQuantSpec and BucketCode::from_vector Add a focused test `rankquant_spec_rejects_bits_8` that asserts both `RankQuantSpec::new(8, 8)` and `BucketCode::from_vector(8, 8, &v)` return `CompositionViolation::InvalidBits { bits: 8 }`, pinning the deliberate b=8 exclusion so the boundary cannot regress silently. Addresses the qodo finding: "bits=8 behavior untested" (PR #226). Signed-off-by: Nelson Spence <nelson@projectnavi.ai> * fix: harden bitmap overlap and BitmapNull against three qodo findings - PackedConstantWeightBitmap::overlap: add assert!(dim <= u32::MAX) before and_popcount, which accumulates into u32 and would overflow silently for very large dims (Finding 1 / Correctness). - top_group_overlap_vector: add assert_eq!(lhs.spec(), rhs.spec()) precondition with a clear message; comparing bitmaps across specs is meaningless (Finding 2 / Maintainability). - BitmapNull::tail_probability(observed): new method returning tail_count(observed) / space_size as f64, the exact hypergeometric upper-tail P(overlap >= observed); rustdoc + unit tests pin boundary values and a known exact result (Finding 3 / Requirement gap). Tests added: packed_overlap_within_u32_max_does_not_panic, top_group_overlap_vector_panics_on_mismatched_spec, top_group_overlap_vector_passes_on_matching_spec, tail_probability_boundary_values, tail_probability_known_value, tail_probability_is_in_unit_interval_and_monotone. Signed-off-by: Nelson Spence <projectnavi@pm.me> Signed-off-by: Nelson Spence <nelson@projectnavi.ai> * docs: product-clean the bucket-code surface (remove internal-prototype references) Replace the "Migration from ordgraph-proto" rustdoc section with a self-contained "Adopting this API" adoption note describing how external callers can replace local forks with the ordvec types. Rename the "ordgraph bucket-code parity gate" test block comment to "bucket-code behavioral contract", describing the invariants under test rather than a migration relationship. No production behaviour, test logic, or assert values changed. Signed-off-by: Nelson Spence <nelson@projectnavi.ai> * docs(const_weight_bitmap): product-clean the bitmap surface (remove internal-prototype references) Replace the module-level "ported to reach parity with..." paragraph with a product-clean adoption note following the pattern established for bucket_code.rs in PR #220. Replace the internal "parity gate" test comment with a behavioral description that explains what the pinned literals assert without naming any internal repository. No production behavior change; no test logic or assertion values changed. Signed-off-by: Nelson Spence <projectnavi@pm.me> Signed-off-by: Nelson Spence <nelson@projectnavi.ai> * fix: honest exactness + gcd-reduced f64 for BitmapNull::tail_probability Two qodo findings on the finite constant-weight null: - (Correctness) tail_probability advertised an 'exact' probability but computed `tail_count as f64 / space_size as f64`, double-rounding two large u128 counts; for C(dim, weight) past 2^53 that can mis-round (e.g. report 1.0 when the true value is just under 1). Reframe: the EXACT surface is the u128 `tail_count` / `space_size`; tail_probability returns the nearest f64, now gcd-reducing the two counts first so the conversion is exact whenever the reduced pair fits an f64 mantissa, and short-circuiting the observed==0 (1.0) and observed>weight (0.0) boundaries with no division. New test pins tail_probability == nearest f64 of the gcd-reduced exact ratio across cases up to C(100,50) ~ 1e29. - (Requirement gap) document that this is an in-model finite null under the idealized uniform constant-weight assumption — a selectivity / false-positive statement, NOT a real-corpus or encoder guarantee and not corpus-calibrated evidence strength. Signed-off-by: Nelson Spence <nelson@projectnavi.ai> --------- Signed-off-by: Nelson Spence <nelson@projectnavi.ai> Signed-off-by: Nelson Spence <projectnavi@pm.me> Co-authored-by: Navi Bot <267427491+project-navi-bot@users.noreply.github.com>
What
Ports
ordgraph-proto/src/code.rsinto ordvec as an index-free bucket-code surface (#220),experimental-gated — so downstream evidence systems (ordgraph-ordvec bridge) consume declared codes instead of forking kernel math.ordvec::{CompositionSpec, RankQuantSpec, BucketCode, CompositionViolation}:CompositionSpec— fixed-composition validation (dim/buckets,expected_per_bucket,histogram,validate_codes).RankQuantSpec—dim+bits ∈ {1,2,4}.BucketCode—new(spec, codes)validated;from_ranks;from_vector(dim, bits, &[f32])(the new ordvec path:rank_transform+rank_to_bucket, output feedsContingency::newfrom Promote bucket-overlap contingency/projection math: dense (pairwise) + indexed (MultiBucketBitmap) #219);top_bitmap.Rank math is not duplicated — delegates to
crate::rank. Parity tests reproduce the proto's exact values, plus validation + afrom_vector↔contingency cross-check. Verified locally: fmt / clippy-D warnings(experimental + default) / test (69 lib + 2 integration; default-build gating confirmed — absent without the feature). No new deps.CompositionViolationenum rather than reusing the crate's flatOrdvecError(the proto's structured values —DuplicateRank{rank},WrongBucketCount{...}— don't fitOrdvecError). AFrom<CompositionViolation> for OrdvecErrorcould unify later. A second public error type is a stable commitment.bits = 8rejected (proto accepted it) — narrowed to ordvec's{1,2,4}packed-format domain. This intersects Decide b=8 RankQuant evidence surface for OrdGraph/Ordscope use #221 (the b=8 decision) — if Decide b=8 RankQuant evidence surface for OrdGraph/Ordscope use #221 later adds b=8,RankQuantSpecextends too. Flagging so Expose reusable RankQuant bucket-code API for downstream evidence systems #220 doesn't silently pre-empt Decide b=8 RankQuant evidence surface for OrdGraph/Ordscope use #221.RankQuantSpecsits next to the existingRankQuantindex type (could read as similar).NonFiniteValueforfrom_vector(fail-softErrvs the crate's usual fail-loud panic at the vector entry point).MismatchedSpecs; derivesHashon all four types (additive).experimentalfor this draft (same as MultiBucketBitmap). Graduation to stable is your call.tests/bucket_code_contingency.rsinlines a reference reimplementation ofContingency::new(which lives in Promote bucket-overlap contingency/projection math: dense (pairwise) + indexed (MultiBucketBitmap) #219, unmerged) and asserts the codes feed it; the swap to the literal type is mechanical once Promote bucket-overlap contingency/projection math: dense (pairwise) + indexed (MultiBucketBitmap) #219 merges.Refs #220. Targets 0.6 (may land in 0.5.0 — maintainer decides).