Skip to content

Clean up config, CI, correctness, and API surface#48

Open
johmathe wants to merge 2 commits into
mainfrom
johmathe/cleanup-config-ci-correctness-api
Open

Clean up config, CI, correctness, and API surface#48
johmathe wants to merge 2 commits into
mainfrom
johmathe/cleanup-config-ci-correctness-api

Conversation

@johmathe
Copy link
Copy Markdown
Collaborator

Tiered cleanup pass. Each tier is a self-contained section of the diff and could in principle be split into separate PRs; collected here for reviewer convenience.

Tier 1 — config + style nits

  • Unify ruff line-length to 120 (drop the pre-commit --line-length=99 override that was fighting pyproject.toml; reformat the repo).
  • Remove dead nbstripout pre-commit hook (no .ipynb files in the repo).
  • Swap archived pre-commit/mirrors-prettier for rbubley/mirrors-prettier@v3.6.2.
  • Drop lone from __future__ import annotations in _cg.py (requires-python>=3.12 makes it unnecessary).
  • Delete orphan docs/selective_so3_on_s2_completeness.log.
  • Convert all _index_map storage to immutable tuples; drop O(N) defensive copies on every index_map property access across all 6 modules.

Tier 2 — wire up the linters that already exist

  • Add typecheck and lockfile jobs to .github/workflows/tests.yml.
  • Expand test matrix to ubuntu-latest + macos-14.
  • Add per-module mypy overrides for register_buffer's Tensor | Module false positives and torch.special's Any returns; ignore_missing_imports for torch_harmonics (no py.typed marker upstream). Strict everywhere else.
  • Fix the 4 real type errors mypy surfaced (no-any-return in _bessel, redef + missing list type arg in so3_on_s2, shadowed loop variable k in dn_on_dn).
  • Track uv.lock; CI verifies via uv lock --check.

Tier 3 — real correctness gaps

  • SO3onS2._cuda_graph_cache is now keyed on (batch_size, dtype, device, grad_enabled) and validates is_contiguous() on replay. Failed captures use a finite cooldown (_CUDA_GRAPH_RETRY_INTERVAL = 256 calls) instead of the permanent {'batch_size': -1} sentinel that disabled the path forever after a single transient error. forward() docstring documents the contract.
  • rotate_spherical_function now emits a UserWarning on fp64 input about the silent grid_sample fp32 downcast; docstring documents the precision contract. Tests updated to either pass fp32 explicitly or pytest.warns if the fp64 path is the SUT.
  • Replace four silent except OSError: pass cache write/read patterns in _cg.py and so3_on_s2.py with logger.warning(...). A read-only ~/.cache/bispectrum no longer eats the entire CG recomputation cost on every import without a peep.
  • Add BISPECTRUM_CACHE_DIR env var override for read-only home dirs (CI, containers, HPC).
  • New tests/test_octa_axioms.py (16 tests) verifies the hardcoded octahedral-group tables: _ELEMENTS_3x3 are valid SO(3) matrices, _CAYLEY matches matrix-mult on all 576 pairs, associative on all 13824 triples, every row/col is a permutation of {0..23}, _INVERSE is involutive and equals transpose, _RHO4_SIGNS is a homomorphism. All pass — tables are sound. Catches future single-character transcription typos.
  • 5 new tests cover the cuda graph cache key invalidation (batch_size mismatch, dtype mismatch) and cooldown decrement behavior.

Tier 4 — honest API surface

  • Add supports_inversion: bool class attribute to all 7 modules (True except SO3onS2). Programmatic check for the open math problem instead of try/except.
  • README: add Inversion column to the supported-groups table with a footnote about SO(3) on S². Replace the "uniform interface" claim with one that documents Module.supports_inversion and the selective=True requirement.
  • README: add a Compatibility section above Installation documenting Python 3.12-only, torch >= 2.10, CUDA driver constraint, and BISPECTRUM_CACHE_DIR override. Currently users hit these as install-time failures.

Verification

  • 593 passed, 22 skipped (pre-existing CUDA skips, no new skips).
  • mypy src/bispectrum: Success: no issues found in 11 source files.
  • pre-commit run --all-files: clean across all 19 hooks.
  • uv lock --check: clean.

Out of scope (separate decisions)

  • Loosening Python floor / making torch_harmonics an extras_require. Real refactor — needs design.
  • GPU CI runner (self-hosted vs. GH gpu vs. Modal/Lambda). Infra decision.
  • Sphinx / mkdocs site. Domain + RTD account decision.
  • Hypothesis property-based tests. Discussed separately, can be its own PR.
  • Benchmarks-on-tag CI. Depends on GPU CI decision.

Test plan

  • CI green on ubuntu + macOS for test, typecheck, lockfile, pre-commit jobs.
  • Local pytest tests/ -n auto against this branch.
  • Sanity: import bispectrum, instantiate one module per group, confirm supports_inversion matches the README table.

Made with Cursor

johmathe and others added 2 commits May 12, 2026 07:16
Tier 1 — config + style:
- Unify ruff line-length to 120 (drop pre-commit override; reformat repo).
- Remove dead nbstripout hook (no .ipynb files in repo).
- Swap archived pre-commit/mirrors-prettier for rbubley/mirrors-prettier.
- Drop lone `from __future__ import annotations` in `_cg.py`.
- Delete orphan `docs/selective_so3_on_s2_completeness.log`.
- Convert all `_index_map` storage to immutable tuples; drop O(N) defensive
  copies on every `index_map` property access across all 6 modules.

Tier 2 — wire up the linters:
- Add `typecheck` and `lockfile` jobs to tests.yml.
- Expand test matrix to ubuntu + macos-14.
- Add per-module mypy overrides for register_buffer Tensor|Module false
  positives and torch.special's `Any` returns; ignore_missing_imports for
  torch_harmonics. Strict everywhere else.
- Fix the 4 real type errors mypy surfaced (no-any-return in `_bessel`,
  redef + missing list type arg in `so3_on_s2`, shadowed loop variable
  in `dn_on_dn`).
- Track `uv.lock`; CI verifies via `uv lock --check`.

Tier 3 — correctness:
- `SO3onS2._cuda_graph_cache`: cache key is now
  `(batch_size, dtype, device, grad_enabled)` and validates
  `is_contiguous()` on replay; failed captures use a finite cooldown
  (`_CUDA_GRAPH_RETRY_INTERVAL = 256` calls) instead of a permanent
  `{'batch_size': -1}` sentinel that disables the path forever.
- `rotate_spherical_function` now emits a UserWarning on fp64 input
  about the silent grid_sample fp32 downcast; docstring documents it.
- Replace four silent `except OSError: pass` cache write/read patterns
  in `_cg.py` and `so3_on_s2.py` with `logger.warning(...)`.
- Add `BISPECTRUM_CACHE_DIR` env var override for read-only home dirs.
- Add `tests/test_octa_axioms.py` (16 tests) verifying `_ELEMENTS_3x3`,
  `_CAYLEY` (matches matmul on all 576 pairs, associative on all 13824
  triples, every row/col is a permutation), `_INVERSE` (involutive,
  equals transpose), and `_RHO4_SIGNS` (homomorphism). All pass.
- Add 5 new tests for the new cuda graph cache key invalidation and
  cooldown behavior.

Tier 4 — honest API:
- Add `supports_inversion: bool` class attribute to all 7 modules
  (True except SO3onS2). Programmatic check for the open math problem
  noted in the README.
- README: add `Inversion` column to supported-groups table with footnote
  about SO(3) on S^2; replace "uniform interface" claim with one that
  documents `supports_inversion` and the `selective=True` requirement.
- README: add `Compatibility` section above Installation documenting
  Python 3.12 only, torch >= 2.10, CUDA driver, and
  `BISPECTRUM_CACHE_DIR` override — currently users hit these as
  install-time failures.

Final: 593 passed, 22 skipped (pre-existing CUDA skips). Mypy clean.
Pre-commit clean across all 19 hooks. `uv lock --check` clean.

Out of scope (separate decisions):
- Loosening Python floor / making torch_harmonics optional.
- GPU CI runner.
- Sphinx/mkdocs site.
- Hypothesis property-based tests.
- Benchmarks-on-tag CI.

Co-authored-by: Cursor <cursoragent@cursor.com>
torch-harmonics 0.9 only ships manylinux_x86_64 wheels — no macOS, no
Windows, no Linux ARM. Adding macos-14 to the matrix in the previous
commit was wrong; uv pip install fails at resolve time:

    Because torch-harmonics==0.9.0 has no wheels with a matching platform
    tag (e.g., `macosx_14_0_arm64`)...

Document the platform constraint in tests.yml (so the next person
doesn't re-add macOS) and in README.md Compatibility section. Will
revisit when torch-harmonics ships broader wheels OR when we move it
to an extras_require.

Co-authored-by: Cursor <cursoragent@cursor.com>
@codecov
Copy link
Copy Markdown

codecov Bot commented May 12, 2026

Codecov Report

❌ Patch coverage is 90.38462% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 95.50%. Comparing base (183431f) to head (9da09a6).

Files with missing lines Patch % Lines
src/bispectrum/so3_on_s2.py 84.21% 6 Missing ⚠️
src/bispectrum/_cg.py 86.36% 3 Missing ⚠️
src/bispectrum/octa_on_octa.py 87.50% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main      #48   +/-   ##
=======================================
  Coverage   95.50%   95.50%           
=======================================
  Files          11       11           
  Lines        2135     2160   +25     
=======================================
+ Hits         2039     2063   +24     
- Misses         96       97    +1     

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

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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