Skip to content

fix(fitstats): fail closed without Rust for chi2_sf and BH - #723

Merged
seonghobae merged 4 commits into
mainfrom
fix/fitstats-rust-required-green
Aug 11, 2026
Merged

fix(fitstats): fail closed without Rust for chi2_sf and BH#723
seonghobae merged 4 commits into
mainfrom
fix/fitstats-rust-required-green

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Why

Advances #720. After #646, public chi2_sf / benjamini_hochberg still silently re-ran pure Python when _core_module() was missing. Production numerical ownership must fail closed.

What

  • Raise RuntimeError("fit statistics require the compiled Rust core") when the core is absent or lacks the entrypoints.
  • Keep the intentional RED contracts from test(fitstats): fail closed without Rust after tail merge #720 as GREEN evidence.
  • Coverage tests that only needed fit-stat helpers while exercising other numpy paths use a stub core with those entrypoints.

Relation

Supersedes draft #720 once this lands (close as absorbed).

Summary by CodeRabbit

  • Bug Fixes

    • Fit-statistics calculations now fail clearly with a stable error when the compiled Rust core is unavailable, instead of silently using alternate calculations.
    • Improved handling and documentation for governed statistical scoring and inference operations.
  • Documentation

    • Added guidance on compiled-core requirements, educational testing, and multiple-testing decisions.
    • Updated the unreleased changelog with changes to scoring, release evidence, and bounded ranking inputs.
  • Tests

    • Added coverage confirming fit-statistics operations fail safely when required compiled functionality is missing.

Require the compiled core for public chi2_sf and benjamini_hochberg so
production numerical ownership cannot silently fall back to pure Python.
Update coverage stubs that only need fit-stat entrypoints for unrelated
numpy-fallback paths.
@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 4fbe4d1f-156e-42ed-a857-b3df12ac083b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The change makes public chi2_sf and benjamini_hochberg require compiled Rust entrypoints. It removes numerical fallbacks, adds capability-error tests, updates fallback test stubs, and documents the behavior.

Changes

Compiled Rust fit-statistics requirement

Layer / File(s) Summary
Rust-only fit-statistics API contract
python/fast_mlsirm/fitstats.py, docs/doctoring/fitstats_rust_required.md, docs/changelog.d/720-fitstats-rust-required.md
The public fit-statistics functions now raise RuntimeError when the required compiled Rust functionality is unavailable.
Fit-statistics fallback and capability tests
tests/test_cov_c_fitstats.py, tests/test_fitstats_rust_required.py
Tests use partial core stubs for Python-owned operations and verify errors for missing or incomplete Rust fit-statistics entrypoints.
Release changelog updates
CHANGELOG.md
The changelog records fit-statistics ownership, governed RAG scoring, Git timeout handling, and bounded LSR ranking materialization.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

🚥 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 and concisely describes the main change: fit-statistics functions fail closed when the compiled Rust core is unavailable.
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 fix/fitstats-rust-required-green

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.

@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: 3

🤖 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 `@CHANGELOG.md`:
- Around line 296-299: Update the “Fit-statistics tail ownership” changelog
entry to state that public chi2_sf and benjamini_hochberg require the compiled
Rust core and fail closed when it is unavailable; remove the claim about a
pure-Python fallback.

In `@docs/doctoring/fitstats_rust_required.md`:
- Around line 9-11: Add stable links and concise source summaries for the cited
AERA/APA/NCME Standards and Benjamini–Hochberg literature in
docs/doctoring/fitstats_rust_required.md; where redistribution is permitted,
include the relevant paper PDFs instead. Preserve the full citations and explain
how each source supports the contract.

In `@python/fast_mlsirm/fitstats.py`:
- Around line 214-217: Update the fit-statistics entrypoint checks in
python/fast_mlsirm/fitstats.py lines 214-217 and 226-231 to retrieve chi2_sf and
benjamini_hochberg respectively, requiring each retrieved entrypoint to be
callable before invoking it; otherwise raise the existing capability
RuntimeError. In tests/test_fitstats_rust_required.py lines 27-38, add a core
sentinel whose entrypoints are non-callable and assert the same capability
error.
🪄 Autofix

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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 4060039e-819b-4a0c-a044-73ac9636e494

📥 Commits

Reviewing files that changed from the base of the PR and between 557a065 and b5fdb2f.

📒 Files selected for processing (6)
  • CHANGELOG.md
  • docs/changelog.d/720-fitstats-rust-required.md
  • docs/doctoring/fitstats_rust_required.md
  • python/fast_mlsirm/fitstats.py
  • tests/test_cov_c_fitstats.py
  • tests/test_fitstats_rust_required.py

Comment thread CHANGELOG.md
Comment on lines +296 to +299
#### Fit-statistics tail ownership

- Public `chi2_sf` and `benjamini_hochberg` now prefer the Rust core for ranking and tail arithmetic, with a pure-Python fallback only when the compiled core methods are unavailable.

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.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Correct the fit-statistics fallback description.

Line 298 still documents a pure-Python fallback. python/fast_mlsirm/fitstats.py:208-229 now raises RuntimeError("fit statistics require the compiled Rust core") when the Rust core or entrypoint is unavailable. Update this entry to state that both APIs require the compiled Rust core and fail closed.

Proposed wording
- Public `chi2_sf` and `benjamini_hochberg` now prefer the Rust core for ranking and tail arithmetic, with a pure-Python fallback only when the compiled core methods are unavailable.
+ Public `chi2_sf` and `benjamini_hochberg` require the compiled Rust core for ranking and tail arithmetic and fail closed when the core methods are unavailable.
📝 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
#### Fit-statistics tail ownership
- Public `chi2_sf` and `benjamini_hochberg` now prefer the Rust core for ranking and tail arithmetic, with a pure-Python fallback only when the compiled core methods are unavailable.
#### Fit-statistics tail ownership
- Public `chi2_sf` and `benjamini_hochberg` require the compiled Rust core for ranking and tail arithmetic and fail closed when the core methods are unavailable.
🤖 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 `@CHANGELOG.md` around lines 296 - 299, Update the “Fit-statistics tail
ownership” changelog entry to state that public chi2_sf and benjamini_hochberg
require the compiled Rust core and fail closed when it is unavailable; remove
the claim about a pure-Python fallback.

Comment on lines +9 to +11
American Educational Research Association, American Psychological Association, & National Council on Measurement in Education. (2014). *Standards for educational and psychological testing*. American Educational Research Association.

Benjamini, Y., & Hochberg, Y. (1995). Controlling the false discovery rate: A practical and powerful approach to multiple testing. *Journal of the Royal Statistical Society: Series B, 57*(1), 289–300.

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

Add links and source summaries for the cited literature.

This document has citations only. Add permitted paper PDFs, or add a stable link and a short summary of the support each source provides for this contract.

As per coding guidelines, “Substantive feature or process PRs should include relevant academic paper PDFs with full citations when redistribution is permissible; otherwise include a citation, link, and summary.”

🤖 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 `@docs/doctoring/fitstats_rust_required.md` around lines 9 - 11, Add stable
links and concise source summaries for the cited AERA/APA/NCME Standards and
Benjamini–Hochberg literature in docs/doctoring/fitstats_rust_required.md; where
redistribution is permitted, include the relevant paper PDFs instead. Preserve
the full citations and explain how each source supports the contract.

Source: Coding guidelines

Comment on lines 214 to +217
core = _core_module()
if core is not None and hasattr(core, "chi2_sf"):
return float(core.chi2_sf(float(x), float(df)))
if df <= 0:
return float("nan")
return _gammainc_upper_reg(df / 2.0, max(x, 0.0) / 2.0)
if core is None or not hasattr(core, "chi2_sf"):
raise RuntimeError("fit statistics require the compiled Rust core")
return float(core.chi2_sf(float(x), float(df)))

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Treat non-callable core attributes as unavailable.

hasattr accepts chi2_sf = None or benjamini_hochberg = None. The subsequent call raises TypeError instead of the stable capability RuntimeError.

  • python/fast_mlsirm/fitstats.py#L214-L217: retrieve chi2_sf and require callable(entrypoint).
  • python/fast_mlsirm/fitstats.py#L226-L231: retrieve benjamini_hochberg and require callable(entrypoint).
  • tests/test_fitstats_rust_required.py#L27-L38: add a core sentinel with non-callable entrypoints and assert the same capability error.
Proposed fix
-    if core is None or not hasattr(core, "chi2_sf"):
+    entrypoint = None if core is None else getattr(core, "chi2_sf", None)
+    if not callable(entrypoint):
         raise RuntimeError("fit statistics require the compiled Rust core")
-    return float(core.chi2_sf(float(x), float(df)))
+    return float(entrypoint(float(x), float(df)))
📍 Affects 2 files
  • python/fast_mlsirm/fitstats.py#L214-L217 (this comment)
  • python/fast_mlsirm/fitstats.py#L226-L231
  • tests/test_fitstats_rust_required.py#L27-L38
🤖 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 `@python/fast_mlsirm/fitstats.py` around lines 214 - 217, Update the
fit-statistics entrypoint checks in python/fast_mlsirm/fitstats.py lines 214-217
and 226-231 to retrieve chi2_sf and benjamini_hochberg respectively, requiring
each retrieved entrypoint to be callable before invoking it; otherwise raise the
existing capability RuntimeError. In tests/test_fitstats_rust_required.py lines
27-38, add a core sentinel whose entrypoints are non-callable and assert the
same capability error.

Partial/incompatible extension objects must not fall into AttributeError on
optional Rust paths or skip fail-closed guards; require hasattr for each
entrypoint before dispatch.

Copy link
Copy Markdown
Contributor Author

@opencode-agent address

Exact-current CI RCA and bounded repair request for PR #723. Before any write, refetch source head 5857b2196dba37e077e499c189efe82b819f85b2 and protected main 20b029a237e7819b5a4f7d74a1b2bbfb1b6755f7; abort this branch if either moved or another source writer appeared.

CI run 31480058221 reached the full production boundary on both Python 3.12 and 3.14. Rust, package/reinstall/release-acceptance, GPU smoke, fuzz, Security Scan and SAST are green. Both Python legs fail only the same stale parity test: tests/test_fitstats.py::test_sx2_extreme_probabilities_preserve_native_numpy_parity. The test computes native s_x2, then monkeypatches _core_module() to None to exercise the still-temporary Python S-X² reference path. After #723 correctly makes public benjamini_hochberg() fail closed without Rust, that reference path now reaches the public BH function and raises RuntimeError("fit statistics require the compiled Rust core"). This is a stale test harness assumption, not evidence that the public BH fallback should be restored.

Minimum remedy only: preserve the S-X² native-vs-reference parity purpose without re-enabling production numerical fallback. In that test, replace the None core with a minimal test-only/reference shim that omits s_x2_stat (therefore forcing the Python S-X² reference branch) but supplies chi2_sf and benjamini_hochberg using explicitly test-local/reference implementations. Reuse the existing private reference helpers already introduced in tests/test_cov_c_fitstats.py where practical, or define the narrowest local shim without importing production fallback behavior. Do not change python/fast_mlsirm/fitstats.py public fail-closed semantics, Rust kernels, thresholds, dependencies, workflows, package version, canonical docs, or unrelated tests.

Acceptance: focused failing test GREEN on both semantics; tests/test_fitstats_rust_required.py remains GREEN and still proves missing/incomplete compiled tail entrypoints fail closed; run focused fitstats tests plus changelog check and git diff --check, commit only the minimal test-harness correction, then stop writing this branch. Fresh full CI/review must run on the new exact head.

Public chi2_sf/BH fail closed when the core is missing; the extreme-probability
parity contract must keep tail helpers available while omitting s_x2_stat so the
NumPy statistic path remains reachable.
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.

1 participant