Skip to content

feat(api)!: make numerical invariants and errors explicit#178

Merged
acgetchell merged 3 commits into
mainfrom
refactor/exact-invariant-proofs
Jul 11, 2026
Merged

feat(api)!: make numerical invariants and errors explicit#178
acgetchell merged 3 commits into
mainfrom
refactor/exact-invariant-proofs

Conversation

@acgetchell

@acgetchell acgetchell commented Jul 11, 2026

Copy link
Copy Markdown
Owner
  • add structured error reasons, locations, origins, and factorization context
  • make determinant, exact-conversion, LU, and LDLT paths range-safe and mathematically explicit
  • validate benchmark inputs independently and require reproducible, provenance-backed performance evidence
  • centralize tool versions, adopt nextest profiles, and replace Codacy with repository-owned checks and SARIF reporting

BREAKING CHANGE: Rename Tolerance::new to Tolerance::try_new and Matrix::get_checked to Matrix::try_get; remove Matrix::set_checked in favor of Matrix::set. Vector::dot and Vector::norm2_sq now borrow their operands. det_sign_exact is now infallible and returns DeterminantSign instead of Result<i8, LaError>. LaError variants now use typed reason, location, and origin fields and require .. in downstream matches. LDLT now requires exact symmetry, determinant error bounds may be unavailable under gradual underflow, and ERR_COEFF_2, ERR_COEFF_3, and ERR_COEFF_4 are no longer exported by the prelude.

Summary by CodeRabbit

  • New Features

    • Added strongly-typed error classifications and clearer diagnostics for invalid tolerances, non-finite computations, singularity, and symmetry violations.
    • Added exact determinant sign and exact-to-f64 conversion APIs (including strict vs rounded conversion), plus a determinant-with-certified-error-bound type.
  • Breaking Changes

    • Renamed Tolerance::new to Tolerance::try_new.
    • Replaced checked matrix access with try_get/validated mutation; Vector::dot and Vector::norm2_sq now take borrowed inputs.
    • det_sign_exact now returns a DeterminantSign value.
  • Documentation

    • Updated README, references, contributing, security, and benchmarking/releasing guidance and examples to match the new APIs/behavior.

- add structured error reasons, locations, origins, and factorization context
- make determinant, exact-conversion, LU, and LDLT paths range-safe and mathematically explicit
- validate benchmark inputs independently and require reproducible, provenance-backed performance evidence
- centralize tool versions, adopt nextest profiles, and replace Codacy with repository-owned checks and SARIF reporting

BREAKING CHANGE: Rename `Tolerance::new` to `Tolerance::try_new` and `Matrix::get_checked` to `Matrix::try_get`; remove `Matrix::set_checked` in favor of `Matrix::set`. `Vector::dot` and `Vector::norm2_sq` now borrow their operands. `det_sign_exact` is now infallible and returns `DeterminantSign` instead of `Result<i8, LaError>`. `LaError` variants now use typed reason, location, and origin fields and require `..` in downstream matches. LDLT now requires exact symmetry, determinant error bounds may be unavailable under gradual underflow, and `ERR_COEFF_2`, `ERR_COEFF_3`, and `ERR_COEFF_4` are no longer exported by the prelude.
@acgetchell acgetchell self-assigned this Jul 11, 2026
@acgetchell acgetchell added this to the v0.4.4 milestone Jul 11, 2026
@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f5bef269-e6ff-41d0-9a8d-fc965277e5a0

📥 Commits

Reviewing files that changed from the base of the PR and between 4ac5af9 and db2fad5.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (44)
  • .github/dependabot.yml
  • .github/workflows/benchmarks.yml
  • .github/workflows/codeql.yml
  • .github/workflows/release-benchmarks.yml
  • .github/workflows/rust-clippy.yml
  • AGENTS.md
  • CONTRIBUTING.md
  • README.md
  • benches/common/exact.rs
  • benches/common/vs_linalg.rs
  • benches/exact.rs
  • benches/vs_linalg.rs
  • docs/BENCHMARKING.md
  • examples/exact_solve_3x3.rs
  • justfile
  • pyproject.toml
  • scripts/README.md
  • scripts/archive_changelog.py
  • scripts/archive_performance.py
  • scripts/bench_compare.py
  • scripts/criterion_dim_plot.py
  • scripts/postprocess_changelog.py
  • scripts/subprocess_utils.py
  • scripts/tag_release.py
  • scripts/tests/test_archive_changelog.py
  • scripts/tests/test_archive_performance.py
  • scripts/tests/test_bench_compare.py
  • scripts/tests/test_criterion_dim_plot.py
  • scripts/tests/test_postprocess_changelog.py
  • scripts/tests/test_subprocess_utils.py
  • scripts/tests/test_tag_release.py
  • semgrep.yaml
  • src/exact.rs
  • src/lib.rs
  • src/matrix.rs
  • src/vector.rs
  • tests/exact_bench_config.rs
  • tests/prelude_exports.rs
  • tests/proptest_factorizations.rs
  • tests/proptest_matrix.rs
  • tests/proptest_vector.rs
  • tests/semgrep/docs/public_examples.md
  • tests/semgrep/src/project_rules/portable_policy.rs
  • tests/vs_linalg_inputs.rs
💤 Files with no reviewable changes (2)
  • .github/workflows/codeql.yml
  • tests/proptest_factorizations.rs
✅ Files skipped from review due to trivial changes (1)
  • scripts/README.md
🚧 Files skipped from review as they are similar to previous changes (27)
  • .github/workflows/rust-clippy.yml
  • tests/prelude_exports.rs
  • CONTRIBUTING.md
  • tests/proptest_vector.rs
  • pyproject.toml
  • scripts/subprocess_utils.py
  • benches/exact.rs
  • examples/exact_solve_3x3.rs
  • .github/workflows/benchmarks.yml
  • tests/proptest_matrix.rs
  • README.md
  • benches/common/exact.rs
  • scripts/tests/test_subprocess_utils.py
  • docs/BENCHMARKING.md
  • benches/common/vs_linalg.rs
  • AGENTS.md
  • tests/vs_linalg_inputs.rs
  • tests/exact_bench_config.rs
  • src/vector.rs
  • semgrep.yaml
  • benches/vs_linalg.rs
  • scripts/criterion_dim_plot.py
  • src/lib.rs
  • scripts/bench_compare.py
  • src/exact.rs
  • scripts/archive_performance.py
  • src/matrix.rs

📝 Walkthrough

Walkthrough

This PR refactors numerical APIs and typed errors, exact arithmetic and factorization kernels, deterministic benchmark/reporting workflows, CI and repository tooling, validation tests, and contributor documentation.

Changes

Numerical API and implementation

Layer / File(s) Summary
Typed errors and fallible public contracts
src/error.rs, src/lib.rs, src/tolerance.rs, src/matrix.rs, src/vector.rs
Adds structured error categories, renames tolerance construction to try_new, replaces checked matrix accessors, exposes row storage, and changes vector operations to borrow operands.
Exact arithmetic and determinant computation
src/exact.rs, src/matrix.rs, src/scaled_product.rs
Introduces typed determinant signs and exact conversion traits, restructures integer/Bareiss computation, and adds range-aware determinant scaling.
LU and LDLT factorization paths
src/lu.rs, src/ldlt.rs
Refactors factor storage, permutation tracking, determinant accumulation, solve execution, and computation-scoped errors.
Numerical validation coverage
tests/*, examples/*, README.md, REFERENCES.md
Updates examples and expands regression, property, conversion-boundary, prelude, factorization, determinant, and cross-library tests.

Benchmark and reporting workflows

Layer / File(s) Summary
Benchmark fixtures and registrations
benches/common/*, benches/exact.rs, benches/vs_linalg.rs, tests/exact_bench_config.rs, tests/vs_linalg_inputs.rs
Reorganizes deterministic fixtures, exact-operation groups, Criterion registrations, validation oracles, stress inputs, and smoke tests.
Benchmark comparison and publication
scripts/bench_compare.py, scripts/archive_performance.py, scripts/criterion_dim_plot.py
Adds confidence-interval assessments, coverage gaps, harness provenance, correctness gates, staged outputs, and atomic publication.
Release and fixture validation
scripts/check_docs_version_sync.py, scripts/check_semgrep_fixtures.py, scripts/tests/*
Validates release references, Semgrep results, benchmark metadata, subprocess input handling, and publication failure paths.

Automation and repository guidance

Layer / File(s) Summary
CI, security, and coverage automation
.github/workflows/*, .config/nextest.toml, rust-toolchain.toml
Updates workflow filters, action pins, audit/SARIF publication, CodeQL languages, Nextest profiles, coverage artifacts, and benchmark gates.
Developer tooling and policy
justfile, Cargo.toml, pyproject.toml, semgrep.yaml, clippy.toml, ty.toml
Adds locked tool execution, dynamic version sourcing, lint/Semgrep rules, package inclusion, dependency changes, and Python 3.14 configuration.
Repository documentation and policies
AGENTS.md, CONTRIBUTING.md, SECURITY.md, docs/*, README.md
Expands API invariants, contributor and release procedures, security intake, coverage, benchmark workflows, and repository guidance.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related issues

Possibly related PRs

Suggested labels: api, breaking change, enhancement, rust, testing

🚥 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 is concise and accurately summarizes the main API change toward explicit numerical invariants and typed errors.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/exact-invariant-proofs

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

@github-advanced-security

Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

@codecov

codecov Bot commented Jul 11, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 99.60630% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 97.75%. Comparing base (3b4b584) to head (db2fad5).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/error.rs 99.60% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #178      +/-   ##
==========================================
- Coverage   98.13%   97.75%   -0.39%     
==========================================
  Files           7        8       +1     
  Lines        3323     4624    +1301     
==========================================
+ Hits         3261     4520    +1259     
- Misses         62      104      +42     
Flag Coverage Δ
unittests 97.75% <99.60%> (-0.39%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
scripts/bench_compare.py (1)

1119-1133: 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Critical: Python 2 exception syntax — module fails to parse.

except ExecutableNotFoundError, subprocess.CalledProcessError: is invalid Python 3 syntax (raises SyntaxError). This breaks importing the entire module, which cascades to main(), all tests in scripts/tests/test_bench_compare.py, and any script importing bench_compare (e.g. archive_performance.py).

🐛 Proposed fix
     try:
         result = run_git_command(["--no-pager", "rev-parse", "--short", "HEAD"], cwd=root)
         short_hash = result.stdout.strip()
-    except ExecutableNotFoundError, subprocess.CalledProcessError:
+    except (ExecutableNotFoundError, subprocess.CalledProcessError):
         pass
     try:
         result = run_git_command(["--no-pager", "rev-parse", "--abbrev-ref", "HEAD"], cwd=root)
         branch = result.stdout.strip()
-    except ExecutableNotFoundError, subprocess.CalledProcessError:
+    except (ExecutableNotFoundError, subprocess.CalledProcessError):
         pass
🤖 Prompt for 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.

In `@scripts/bench_compare.py` around lines 1119 - 1133, Fix the invalid exception
syntax in _get_git_info by using Python 3 tuple syntax to catch both
ExecutableNotFoundError and subprocess.CalledProcessError in each try block,
preserving the existing fallback behavior.
🧹 Nitpick comments (3)
scripts/criterion_dim_plot.py (1)

872-890: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Inconsistent type for criterion.benchmark_command provenance field.

benchmark_command is a list[str] when measurement_recorded is true but the bare string "unavailable" otherwise. Consumers of this JSON (including the README publication test that indexes [:3]) would break if they don't special-case the exploratory branch. Consider using a consistently-typed value (e.g. None, or always a list with a sentinel) for a stable schema.

🤖 Prompt for 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.

In `@scripts/criterion_dim_plot.py` around lines 872 - 890, Make
criterion.benchmark_command type-consistent in the returned provenance object:
update the conditional in the result-building function to use a single stable
representation, preferably None when measurement_recorded is false and the
existing list when true. Update any consumers or schema expectations, including
README publication handling, to support the chosen representation without
indexing a string sentinel.
src/error.rs (1)

532-548: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

invalid_tolerance can mislabel a valid tolerance if misused externally.

This pub const fn infers InvalidToleranceReason solely from value.is_finite(), trusting that the caller already confirmed value violates the invariant. If an external caller invokes LaError::invalid_tolerance(5.0) directly (a valid, non-negative finite value), it silently constructs InvalidTolerance { value: 5.0, reason: Negative } — a logically wrong, misleading error. The doc comment flags this as a precondition, but nothing enforces it for a public API.

Consider either accepting an explicit InvalidToleranceReason from the caller (mirroring how singular_numerical takes explicit typed fields) or debug_assert!-checking the precondition to catch misuse in tests/debug builds.

♻️ Proposed direction
-    pub const fn invalid_tolerance(value: f64) -> Self {
-        let reason = if value.is_finite() {
-            InvalidToleranceReason::Negative
-        } else {
-            InvalidToleranceReason::NotFinite
-        };
-        Self::InvalidTolerance { value, reason }
-    }
+    pub const fn invalid_tolerance(value: f64) -> Self {
+        debug_assert!(
+            !value.is_finite() || value < 0.0,
+            "invalid_tolerance called with a value that satisfies the tolerance invariant"
+        );
+        let reason = if value.is_finite() {
+            InvalidToleranceReason::Negative
+        } else {
+            InvalidToleranceReason::NotFinite
+        };
+        Self::InvalidTolerance { value, reason }
+    }
🤖 Prompt for 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.

In `@src/error.rs` around lines 532 - 548, Harden the public constructor
invalid_tolerance against valid inputs being mislabeled: either change it to
accept an explicit InvalidToleranceReason, or retain inference while adding a
debug_assert! that value is non-finite or negative before constructing
InvalidTolerance. Update all callers and documentation to match the chosen
contract, preserving the NotFinite precedence for negative infinity.
scripts/bench_compare.py (1)

916-919: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Unused assessment parameter in _format_pct.

The parameter is immediately discarded (del assessment) and never affects output. Consider dropping it from the signature and call sites if no future use is planned, or keep as-is if intentionally reserved for future formatting.

🤖 Prompt for 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.

In `@scripts/bench_compare.py` around lines 916 - 919, The _format_pct function
accepts an unused assessment parameter and immediately discards it; remove
assessment from the function signature and update every call site accordingly,
unless it is intentionally retained for planned formatting behavior.
🤖 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 `@AGENTS.md`:
- Around line 133-139: Repair the bullet list under “Testing mirrors the
principles” by keeping the “Unit tests cover known values, error paths, and
dimension-generic correctness across D=2..=5 (see Dimension Coverage below)”
text as one bullet, then placing “Error-path tests match the exact variant...”
as a separate bullet.

In `@scripts/criterion_dim_plot.py`:
- Around line 739-745: Fix the invalid Python exception syntax by parenthesizing
the exception tuples: update the except clauses in _git_value,
_git_status_metadata, and _rustc_version to use `except
(ExecutableNotFoundError, subprocess.CalledProcessError):`.
- Around line 670-687: Pin the rollback temporary directory to the benchmark
root in _run_publication_benchmarks by passing dir=root to
tempfile.TemporaryDirectory, matching _stage_and_publish_outputs so staged files
remain on the same filesystem as target/criterion before Path.replace restores
them.

In `@scripts/subprocess_utils.py`:
- Line 184: Update both exception handlers in the relevant subprocess utility
functions to use Python 3 tuple syntax: replace `except ExecutableNotFoundError,
subprocess.CalledProcessError:` with `except (ExecutableNotFoundError,
subprocess.CalledProcessError):`.

---

Outside diff comments:
In `@scripts/bench_compare.py`:
- Around line 1119-1133: Fix the invalid exception syntax in _get_git_info by
using Python 3 tuple syntax to catch both ExecutableNotFoundError and
subprocess.CalledProcessError in each try block, preserving the existing
fallback behavior.

---

Nitpick comments:
In `@scripts/bench_compare.py`:
- Around line 916-919: The _format_pct function accepts an unused assessment
parameter and immediately discards it; remove assessment from the function
signature and update every call site accordingly, unless it is intentionally
retained for planned formatting behavior.

In `@scripts/criterion_dim_plot.py`:
- Around line 872-890: Make criterion.benchmark_command type-consistent in the
returned provenance object: update the conditional in the result-building
function to use a single stable representation, preferably None when
measurement_recorded is false and the existing list when true. Update any
consumers or schema expectations, including README publication handling, to
support the chosen representation without indexing a string sentinel.

In `@src/error.rs`:
- Around line 532-548: Harden the public constructor invalid_tolerance against
valid inputs being mislabeled: either change it to accept an explicit
InvalidToleranceReason, or retain inference while adding a debug_assert! that
value is non-finite or negative before constructing InvalidTolerance. Update all
callers and documentation to match the chosen contract, preserving the NotFinite
precedence for negative infinity.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: c9a226d6-c2c9-4658-b356-2ee85d1ac055

📥 Commits

Reviewing files that changed from the base of the PR and between 3b4b584 and 668daed.

⛔ Files ignored due to path filters (2)
  • Cargo.lock is excluded by !**/*.lock
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (85)
  • .codacy.yml
  • .config/nextest.toml
  • .github/workflows/audit.yml
  • .github/workflows/benchmarks.yml
  • .github/workflows/ci.yml
  • .github/workflows/codacy.yml
  • .github/workflows/codecov.yml
  • .github/workflows/codeql.yml
  • .github/workflows/release-benchmarks.yml
  • .github/workflows/rust-clippy.yml
  • .github/workflows/semgrep-sarif.yml
  • .markdownlint.json
  • .python-version
  • .yamllint
  • AGENTS.md
  • CONTRIBUTING.md
  • Cargo.toml
  • README.md
  • REFERENCES.md
  • SECURITY.md
  • benches/common/exact.rs
  • benches/common/vs_linalg.rs
  • benches/exact.rs
  • benches/vs_linalg.rs
  • clippy.toml
  • docs/BENCHMARKING.md
  • docs/COVERAGE.md
  • docs/PERFORMANCE.md
  • docs/RELEASING.md
  • docs/assets/bench/vs_linalg_lu_solve_median.provenance.json
  • docs/roadmap.md
  • dprint.json
  • examples/const_det_4x4.rs
  • examples/det_5x5.rs
  • examples/exact_det_3x3.rs
  • examples/exact_sign_3x3.rs
  • examples/exact_solve_3x3.rs
  • examples/ldlt_solve_3x3.rs
  • examples/solve_5x5.rs
  • justfile
  • pyproject.toml
  • rust-toolchain.toml
  • scripts/README.md
  • scripts/archive_changelog.py
  • scripts/archive_performance.py
  • scripts/bench_compare.py
  • scripts/check_docs_version_sync.py
  • scripts/check_semgrep_fixtures.py
  • scripts/criterion_dim_plot.py
  • scripts/postprocess_changelog.py
  • scripts/subprocess_utils.py
  • scripts/tests/__init__.py
  • scripts/tests/test_archive_performance.py
  • scripts/tests/test_bench_compare.py
  • scripts/tests/test_check_docs_version_sync.py
  • scripts/tests/test_check_semgrep_fixtures.py
  • scripts/tests/test_criterion_dim_plot.py
  • scripts/tests/test_subprocess_utils.py
  • scripts/tests/test_tag_release.py
  • semgrep.yaml
  • src/error.rs
  • src/exact.rs
  • src/ldlt.rs
  • src/lib.rs
  • src/lu.rs
  • src/matrix.rs
  • src/scaled_product.rs
  • src/tolerance.rs
  • src/vector.rs
  • tests/exact_bench_config.rs
  • tests/exact_conversion_boundaries.rs
  • tests/prelude_exports.rs
  • tests/proptest_exact.rs
  • tests/proptest_factorizations.rs
  • tests/proptest_matrix.rs
  • tests/proptest_vector.rs
  • tests/regressions.rs
  • tests/scaled_product_determinants.rs
  • tests/semgrep/.github/workflows/action_policy.yml
  • tests/semgrep/docs/public_examples.md
  • tests/semgrep/scripts/tests/python_exceptions.py
  • tests/semgrep/src/project_rules/finite_api_contract.rs
  • tests/semgrep/src/project_rules/portable_policy.rs
  • tests/vs_linalg_inputs.rs
  • ty.toml
💤 Files with no reviewable changes (4)
  • .codacy.yml
  • .github/workflows/codacy.yml
  • ty.toml
  • .markdownlint.json

Comment thread AGENTS.md
Comment on lines 133 to 139
### Testing mirrors the principles

- Unit tests cover known values, error paths, and dimension-generic
- Error-path tests match the exact variant, typed reason/origin/location, and
structured fields; do not replace an unexpected error with a numeric sentinel
or assert only `is_err()`.
correctness across D=2..=5 (see **Dimension Coverage** below).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Bullet list corrupted — sentence spliced into the wrong bullet.

The new "Error-path tests..." bullet was inserted between the "Unit tests..." bullet and its own wrapped continuation line. As rendered, the first bullet now dead-ends at "dimension-generic" and the orphaned "correctness across D=2..=5 (see Dimension Coverage below)." sentence is attached to the unrelated second bullet instead.

📝 Proposed fix
-- Unit tests cover known values, error paths, and dimension-generic
-- Error-path tests match the exact variant, typed reason/origin/location, and
-  structured fields; do not replace an unexpected error with a numeric sentinel
-  or assert only `is_err()`.
-  correctness across D=2..=5 (see **Dimension Coverage** below).
+- Unit tests cover known values, error paths, and dimension-generic
+  correctness across D=2..=5 (see **Dimension Coverage** below).
+- Error-path tests match the exact variant, typed reason/origin/location, and
+  structured fields; do not replace an unexpected error with a numeric sentinel
+  or assert only `is_err()`.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
### Testing mirrors the principles
- Unit tests cover known values, error paths, and dimension-generic
- Error-path tests match the exact variant, typed reason/origin/location, and
structured fields; do not replace an unexpected error with a numeric sentinel
or assert only `is_err()`.
correctness across D=2..=5 (see **Dimension Coverage** below).
### Testing mirrors the principles
- Unit tests cover known values, error paths, and dimension-generic
correctness across D=2..=5 (see **Dimension Coverage** below).
- Error-path tests match the exact variant, typed reason/origin/location, and
structured fields; do not replace an unexpected error with a numeric sentinel
or assert only `is_err()`.
🤖 Prompt for 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.

In `@AGENTS.md` around lines 133 - 139, Repair the bullet list under “Testing
mirrors the principles” by keeping the “Unit tests cover known values, error
paths, and dimension-generic correctness across D=2..=5 (see Dimension Coverage
below)” text as one bullet, then placing “Error-path tests match the exact
variant...” as a separate bullet.

Comment thread scripts/criterion_dim_plot.py
Comment thread scripts/criterion_dim_plot.py
Comment thread scripts/subprocess_utils.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
benches/common/exact.rs (1)

22-49: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Mark ExactBenchConfigError and UnorderedRange as #[non_exhaustive]
ExactBenchConfigError and ExactBenchConfigError::UnorderedRange should be #[non_exhaustive] so this public configuration error can evolve without breaking matches. I16Range is already #[must_use].

🤖 Prompt for 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.

In `@benches/common/exact.rs` around lines 22 - 49, Mark the public
ExactBenchConfigError enum and its UnorderedRange variant with
#[non_exhaustive]. Leave I16Range unchanged, as it already has #[must_use].

Source: Coding guidelines

🤖 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 `@benches/common/vs_linalg.rs`:
- Around line 127-140: Restrict make_ill_conditioned_matrix_rows to its
supported dimension D=8, updating its signature and documentation so callers
cannot request dimensions where diagonal scaling underflows; adjust any call
sites or tests accordingly. Alternatively, retain genericity only by returning a
typed failure for unsupported dimensions, while ensuring the fixture never
produces zero diagonal entries or violates positive-definiteness.

In `@Cargo.toml`:
- Around line 14-33: Update the Cargo.toml package include whitelist to include
the checked-in docs/assets/bench/*.provenance.json provenance artifact,
preserving the existing asset patterns and formatting the TOML with the
repository’s just toml-* commands.

In `@scripts/archive_changelog.py`:
- Around line 315-338: Update _archive_dir_link_prefix to fail with a clear
exception when os.path.relpath() raises ValueError, rather than falling back to
archive_dir.as_posix(); ensure archive_changelog() propagates or handles this
failure before rewriting CHANGELOG.md. Add a regression test simulating
cross-volume paths and verify no changelog rewrite occurs and no absolute
filesystem path is emitted.

In `@scripts/archive_performance.py`:
- Around line 1038-1042: Update the fallback branch in the current benchmark
command selection to choose the cargo benchmark and feature arguments based on
config.suite, matching the suite-specific split implemented by
_baseline_tool_args; ensure vs_linalg runs its corresponding benchmark instead
of always running exact.

In `@scripts/bench_compare.py`:
- Around line 1216-1290: Update _provenance_markdown to render correctness-gate
wording based on the provenance mode: retain “shared current fixture harness”
only for current/shared-harness validation, and use wording that accurately
describes historical-assets validation without asserting an unverified harness.
Add or update tests covering historical-assets mode with unavailable measurement
metadata, verifying the published provenance contains only mode-appropriate
wording.

In `@scripts/check_docs_version_sync.py`:
- Around line 260-263: Update _README_TAG_LINK_RE so prerelease and build
metadata suffixes are independently optional, allowing versions such as
v1.2.3-rc.1+build.7 to match; add or update the relevant tests to verify both
combined suffixes and existing version formats.

In `@scripts/criterion_dim_plot.py`:
- Around line 689-702: Update _run_publication_command to also catch
ExecutableNotFoundError and subprocess.TimeoutExpired from run_safe_command,
converting both into RuntimeError with the command and relevant failure details
preserved. Keep CalledProcessError handling intact so every publication-command
failure reaches main’s staging rollback path.
- Around line 743-744: Replace each invalid multi-exception handler in the
relevant functions with Python 3 parenthesized exception tuple syntax, covering
ExecutableNotFoundError and subprocess.CalledProcessError at all three
occurrences.

In `@scripts/subprocess_utils.py`:
- Line 184: Update the exception handlers in the relevant subprocess utility
function to use Python 3 tuple syntax, changing both `except
ExecutableNotFoundError, subprocess.CalledProcessError` clauses to catch
`(ExecutableNotFoundError, subprocess.CalledProcessError)`, so the module
imports cleanly.

---

Outside diff comments:
In `@benches/common/exact.rs`:
- Around line 22-49: Mark the public ExactBenchConfigError enum and its
UnorderedRange variant with #[non_exhaustive]. Leave I16Range unchanged, as it
already has #[must_use].
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: c9a226d6-c2c9-4658-b356-2ee85d1ac055

📥 Commits

Reviewing files that changed from the base of the PR and between 3b4b584 and 668daed.

⛔ Files ignored due to path filters (2)
  • Cargo.lock is excluded by !**/*.lock
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (85)
  • .codacy.yml
  • .config/nextest.toml
  • .github/workflows/audit.yml
  • .github/workflows/benchmarks.yml
  • .github/workflows/ci.yml
  • .github/workflows/codacy.yml
  • .github/workflows/codecov.yml
  • .github/workflows/codeql.yml
  • .github/workflows/release-benchmarks.yml
  • .github/workflows/rust-clippy.yml
  • .github/workflows/semgrep-sarif.yml
  • .markdownlint.json
  • .python-version
  • .yamllint
  • AGENTS.md
  • CONTRIBUTING.md
  • Cargo.toml
  • README.md
  • REFERENCES.md
  • SECURITY.md
  • benches/common/exact.rs
  • benches/common/vs_linalg.rs
  • benches/exact.rs
  • benches/vs_linalg.rs
  • clippy.toml
  • docs/BENCHMARKING.md
  • docs/COVERAGE.md
  • docs/PERFORMANCE.md
  • docs/RELEASING.md
  • docs/assets/bench/vs_linalg_lu_solve_median.provenance.json
  • docs/roadmap.md
  • dprint.json
  • examples/const_det_4x4.rs
  • examples/det_5x5.rs
  • examples/exact_det_3x3.rs
  • examples/exact_sign_3x3.rs
  • examples/exact_solve_3x3.rs
  • examples/ldlt_solve_3x3.rs
  • examples/solve_5x5.rs
  • justfile
  • pyproject.toml
  • rust-toolchain.toml
  • scripts/README.md
  • scripts/archive_changelog.py
  • scripts/archive_performance.py
  • scripts/bench_compare.py
  • scripts/check_docs_version_sync.py
  • scripts/check_semgrep_fixtures.py
  • scripts/criterion_dim_plot.py
  • scripts/postprocess_changelog.py
  • scripts/subprocess_utils.py
  • scripts/tests/__init__.py
  • scripts/tests/test_archive_performance.py
  • scripts/tests/test_bench_compare.py
  • scripts/tests/test_check_docs_version_sync.py
  • scripts/tests/test_check_semgrep_fixtures.py
  • scripts/tests/test_criterion_dim_plot.py
  • scripts/tests/test_subprocess_utils.py
  • scripts/tests/test_tag_release.py
  • semgrep.yaml
  • src/error.rs
  • src/exact.rs
  • src/ldlt.rs
  • src/lib.rs
  • src/lu.rs
  • src/matrix.rs
  • src/scaled_product.rs
  • src/tolerance.rs
  • src/vector.rs
  • tests/exact_bench_config.rs
  • tests/exact_conversion_boundaries.rs
  • tests/prelude_exports.rs
  • tests/proptest_exact.rs
  • tests/proptest_factorizations.rs
  • tests/proptest_matrix.rs
  • tests/proptest_vector.rs
  • tests/regressions.rs
  • tests/scaled_product_determinants.rs
  • tests/semgrep/.github/workflows/action_policy.yml
  • tests/semgrep/docs/public_examples.md
  • tests/semgrep/scripts/tests/python_exceptions.py
  • tests/semgrep/src/project_rules/finite_api_contract.rs
  • tests/semgrep/src/project_rules/portable_policy.rs
  • tests/vs_linalg_inputs.rs
  • ty.toml
💤 Files with no reviewable changes (4)
  • .codacy.yml
  • .markdownlint.json
  • .github/workflows/codacy.yml
  • ty.toml

Comment thread benches/common/vs_linalg.rs
Comment thread Cargo.toml
Comment thread scripts/archive_changelog.py
Comment thread scripts/archive_performance.py
Comment thread scripts/bench_compare.py
Comment thread scripts/check_docs_version_sync.py
Comment thread scripts/criterion_dim_plot.py
Comment thread scripts/criterion_dim_plot.py Outdated
Comment thread scripts/subprocess_utils.py Outdated
- Adapt the shared benchmark harness across v0.4.3 API differences without changing measured operations
- Exclude invalid balanced-range baselines while requiring current samples and reporting unavailable comparisons
- Preserve benchmark provenance, suite-specific fallback commands, and publication rollback guarantees
- Harden Windows Git input, changelog links, and version-reference parsing across platforms

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
benches/common/vs_linalg.rs (1)

59-112: 🚀 Performance & Scalability | 🟡 Minor | ⚡ Quick win

Move det(P) out of the timed path
faer_det_from_partial_piv_lu still computes faer_perm_sign(lu.P()) inside the benchmarked bencher.iter closure, so this parity work is part of the measured faer_det_from_lu result. Precompute the sign before timing, or benchmark parity separately, to keep the comparison focused on determinant work.

🤖 Prompt for 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.

In `@benches/common/vs_linalg.rs` around lines 59 - 112, Move the
faer_perm_sign(lu.P()) computation out of the bencher.iter closure in
faer_det_from_partial_piv_lu by calculating it before timing and reusing the
result inside the closure. Keep the benchmark’s timed path focused on
determinant computation while preserving the existing determinant result.

Source: Learnings

🤖 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 `@scripts/tests/test_archive_changelog.py`:
- Around line 465-466: Update the assertions in the archive changelog test to
verify that both archive_dir’s native string representation and its POSIX
representation are absent from root and str(exc_info.value). Preserve the
existing leak checks while covering Windows backslash paths as well as
slash-separated paths.

---

Outside diff comments:
In `@benches/common/vs_linalg.rs`:
- Around line 59-112: Move the faer_perm_sign(lu.P()) computation out of the
bencher.iter closure in faer_det_from_partial_piv_lu by calculating it before
timing and reusing the result inside the closure. Keep the benchmark’s timed
path focused on determinant computation while preserving the existing
determinant result.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: a4f5470d-2e47-40b9-b4c6-6dfb1358b843

📥 Commits

Reviewing files that changed from the base of the PR and between 668daed and 4ac5af9.

📒 Files selected for processing (22)
  • Cargo.toml
  • benches/common/exact.rs
  • benches/common/vs_linalg.rs
  • benches/vs_linalg.rs
  • docs/BENCHMARKING.md
  • scripts/archive_changelog.py
  • scripts/archive_performance.py
  • scripts/bench_compare.py
  • scripts/check_docs_version_sync.py
  • scripts/criterion_dim_plot.py
  • scripts/subprocess_utils.py
  • scripts/tests/test_archive_changelog.py
  • scripts/tests/test_archive_performance.py
  • scripts/tests/test_bench_compare.py
  • scripts/tests/test_check_docs_version_sync.py
  • scripts/tests/test_criterion_dim_plot.py
  • scripts/tests/test_subprocess_utils.py
  • src/error.rs
  • src/ldlt.rs
  • src/matrix.rs
  • src/scaled_product.rs
  • tests/vs_linalg_inputs.rs
🚧 Files skipped from review as they are similar to previous changes (16)
  • scripts/archive_changelog.py
  • Cargo.toml
  • scripts/tests/test_check_docs_version_sync.py
  • benches/vs_linalg.rs
  • scripts/check_docs_version_sync.py
  • benches/common/exact.rs
  • tests/vs_linalg_inputs.rs
  • src/error.rs
  • scripts/tests/test_criterion_dim_plot.py
  • src/ldlt.rs
  • scripts/tests/test_archive_performance.py
  • scripts/criterion_dim_plot.py
  • scripts/archive_performance.py
  • docs/BENCHMARKING.md
  • scripts/bench_compare.py
  • src/matrix.rs

Comment thread scripts/tests/test_archive_changelog.py
- add `DeterminantWithErrorBound` for paired determinant estimates and certified bounds
- scale exact systems independently and round exact values directly to IEEE-754
- fail benchmark publication closed on invalid samples or mismatched provenance
- make release and changelog tooling transactional, path-safe, and Windows-portable
- align benchmark CI with pinned local tools and least-privilege publishing
@acgetchell acgetchell enabled auto-merge July 11, 2026 16:25
@acgetchell acgetchell merged commit 6c79012 into main Jul 11, 2026
21 checks passed
@acgetchell acgetchell deleted the refactor/exact-invariant-proofs branch July 11, 2026 17:03
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