lme-python 0.1.11__tar.gz → 0.2.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (358) hide show
  1. lme_python-0.2.2/.github/dependabot.yml +10 -0
  2. lme_python-0.2.2/.github/workflows/audit.yml +62 -0
  3. {lme_python-0.1.11 → lme_python-0.2.2}/.github/workflows/benchmarks.yml +21 -12
  4. lme_python-0.2.2/.github/workflows/cache-prime.yml +121 -0
  5. lme_python-0.2.2/.github/workflows/ci.yml +267 -0
  6. {lme_python-0.1.11 → lme_python-0.2.2}/.github/workflows/crate-publish-dry-run.yml +14 -9
  7. {lme_python-0.1.11 → lme_python-0.2.2}/.github/workflows/fuzz-smoke.yml +17 -6
  8. lme_python-0.2.2/.github/workflows/python-release.yml +262 -0
  9. {lme_python-0.1.11 → lme_python-0.2.2}/.github/workflows/repo-metadata.yml +1 -1
  10. lme_python-0.2.2/AGENTS.md +112 -0
  11. {lme_python-0.1.11 → lme_python-0.2.2}/BENCHMARKS.md +50 -23
  12. {lme_python-0.1.11 → lme_python-0.2.2}/BENCHMARK_COVERAGE.md +38 -22
  13. {lme_python-0.1.11 → lme_python-0.2.2}/CHANGELOG.md +68 -4
  14. lme_python-0.2.2/CI_PERFORMANCE.md +63 -0
  15. {lme_python-0.1.11 → lme_python-0.2.2}/CONTRIBUTING.md +21 -13
  16. {lme_python-0.1.11 → lme_python-0.2.2}/Cargo.lock +9 -171
  17. {lme_python-0.1.11 → lme_python-0.2.2}/Cargo.toml +15 -3
  18. {lme_python-0.1.11 → lme_python-0.2.2}/GUIDE.md +145 -23
  19. {lme_python-0.1.11 → lme_python-0.2.2}/OPTIMIZATION.md +107 -20
  20. lme_python-0.2.2/PKG-INFO +67 -0
  21. {lme_python-0.1.11 → lme_python-0.2.2}/README.md +16 -14
  22. {lme_python-0.1.11 → lme_python-0.2.2}/RELEASING.md +51 -20
  23. lme_python-0.2.2/REPO_COMPLETION_BY_AREA.md +110 -0
  24. {lme_python-0.1.11 → lme_python-0.2.2}/Taskfile.yml +33 -3
  25. {lme_python-0.1.11 → lme_python-0.2.2}/USABILITY.md +20 -18
  26. {lme_python-0.1.11 → lme_python-0.2.2}/benches/bench_math.rs +51 -0
  27. lme_python-0.2.2/benchmarks/external-nlmm-inference-python-timings-2026-08-14.json +198 -0
  28. lme_python-0.2.2/benchmarks/fair-rust-julia-reference-2026-07-16-cold-fit-lt1.json +363 -0
  29. lme_python-0.2.2/benchmarks/fair-rust-julia-reference-2026-07-22-full-tier-a.json +1593 -0
  30. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/COMPARISONS.md +24 -5
  31. lme_python-0.2.2/comparisons/bench_external_timings.R +138 -0
  32. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/bench_fair_julia_timing.jl +2 -1
  33. lme_python-0.2.2/comparisons/pastes_emmeans.R +48 -0
  34. lme_python-0.2.2/comparisons/pastes_glht.R +36 -0
  35. lme_python-0.2.2/comparisons/sleepstudy_confint_profile.R +16 -0
  36. lme_python-0.2.2/completion_manifest.json +20 -0
  37. {lme_python-0.1.11 → lme_python-0.2.2}/docs/CALO_CALIBRATION.md +2 -2
  38. lme_python-0.2.2/examples/bench_external_timings.rs +262 -0
  39. lme_python-0.2.2/examples/dump_cascade_fixtures.rs +339 -0
  40. lme_python-0.2.2/examples/explore_formula_ast.rs +137 -0
  41. lme_python-0.2.2/examples/explore_mcp_adjust.rs +78 -0
  42. lme_python-0.2.2/examples/explore_theta_grid.rs +76 -0
  43. {lme_python-0.1.11 → lme_python-0.2.2}/legal/fixture-provenance.json +6 -1
  44. {lme_python-0.1.11 → lme_python-0.2.2}/pyproject.toml +8 -0
  45. {lme_python-0.1.11 → lme_python-0.2.2}/python/Cargo.lock +10 -172
  46. {lme_python-0.1.11 → lme_python-0.2.2}/python/Cargo.toml +2 -1
  47. {lme_python-0.1.11 → lme_python-0.2.2}/python/PYTHON_GUIDE.md +115 -24
  48. lme_python-0.2.2/python/README.md +44 -0
  49. {lme_python-0.1.11 → lme_python-0.2.2}/python/examples/verification_project/parity.py +5 -3
  50. {lme_python-0.1.11 → lme_python-0.2.2}/python/examples/verification_project/run.py +1 -1
  51. {lme_python-0.1.11 → lme_python-0.2.2}/python/lme_python.pyi +126 -3
  52. {lme_python-0.1.11 → lme_python-0.2.2}/python/src/lib.rs +919 -207
  53. {lme_python-0.1.11 → lme_python-0.2.2}/python/tests/test_api_parity.py +59 -9
  54. {lme_python-0.1.11 → lme_python-0.2.2}/python/tests/test_cv.py +20 -0
  55. {lme_python-0.1.11 → lme_python-0.2.2}/python/tests/test_nlmer_custom_mean.py +25 -0
  56. {lme_python-0.1.11 → lme_python-0.2.2}/scripts/ci/README.md +7 -3
  57. lme_python-0.2.2/scripts/ci/check_completion_score.py +101 -0
  58. {lme_python-0.1.11 → lme_python-0.2.2}/scripts/ci/lme_ci.py +447 -33
  59. lme_python-0.2.2/scripts/explorations/README.md +20 -0
  60. lme_python-0.2.2/scripts/run_external_timings.py +236 -0
  61. {lme_python-0.1.11 → lme_python-0.2.2}/scripts/run_fair_rust_julia_benchmark.py +2 -2
  62. lme_python-0.2.2/src/basis.rs +529 -0
  63. {lme_python-0.1.11 → lme_python-0.2.2}/src/bootstrap.rs +294 -18
  64. {lme_python-0.1.11 → lme_python-0.2.2}/src/contrast.rs +16 -12
  65. {lme_python-0.1.11 → lme_python-0.2.2}/src/cv.rs +309 -2
  66. lme_python-0.2.2/src/emmeans.rs +459 -0
  67. {lme_python-0.1.11 → lme_python-0.2.2}/src/family.rs +65 -0
  68. lme_python-0.2.2/src/formula.rs +1360 -0
  69. {lme_python-0.1.11 → lme_python-0.2.2}/src/glmm_math.rs +154 -47
  70. {lme_python-0.1.11 → lme_python-0.2.2}/src/intercept_blocked.rs +43 -3
  71. {lme_python-0.1.11 → lme_python-0.2.2}/src/kenward_roger.rs +48 -20
  72. {lme_python-0.1.11 → lme_python-0.2.2}/src/lib.rs +317 -106
  73. {lme_python-0.1.11 → lme_python-0.2.2}/src/math.rs +90 -34
  74. lme_python-0.2.2/src/mcp.rs +350 -0
  75. {lme_python-0.1.11 → lme_python-0.2.2}/src/model_matrix.rs +784 -295
  76. {lme_python-0.1.11 → lme_python-0.2.2}/src/nlmm/fit.rs +269 -7
  77. {lme_python-0.1.11 → lme_python-0.2.2}/src/nlmm/formula.rs +46 -3
  78. {lme_python-0.1.11 → lme_python-0.2.2}/src/nlmm/mean.rs +10 -0
  79. {lme_python-0.1.11 → lme_python-0.2.2}/src/nlmm/mean_fn.rs +26 -1
  80. {lme_python-0.1.11 → lme_python-0.2.2}/src/nlmm/mod.rs +15 -1
  81. {lme_python-0.1.11 → lme_python-0.2.2}/src/nlmm/self_start.rs +100 -0
  82. lme_python-0.2.2/src/nlmm/ssasympoff.rs +46 -0
  83. lme_python-0.2.2/src/nlmm/ssasymporig.rs +43 -0
  84. lme_python-0.2.2/src/nlmm/ssbiexp.rs +49 -0
  85. lme_python-0.2.2/src/nlmm/ssfpl.rs +50 -0
  86. lme_python-0.2.2/src/nlmm/ssweibull.rs +53 -0
  87. {lme_python-0.1.11 → lme_python-0.2.2}/src/optimizer.rs +221 -13
  88. {lme_python-0.1.11 → lme_python-0.2.2}/src/perf_diag.rs +2 -1
  89. lme_python-0.2.2/src/profile_ci.rs +1118 -0
  90. {lme_python-0.1.11 → lme_python-0.2.2}/src/robust.rs +3 -2
  91. {lme_python-0.1.11 → lme_python-0.2.2}/src/satterthwaite.rs +2 -0
  92. {lme_python-0.1.11 → lme_python-0.2.2}/src/simulate.rs +49 -9
  93. lme_python-0.2.2/src/studentized_range.rs +224 -0
  94. lme_python-0.2.2/tests/ci_consolidated.rs +112 -0
  95. lme_python-0.2.2/tests/data/dyestuff_intercept_reml.json +17 -0
  96. lme_python-0.2.2/tests/data/glmm_binomial_agq.json +9 -0
  97. lme_python-0.2.2/tests/data/glmm_binomial_cloglog.json +19 -0
  98. lme_python-0.2.2/tests/data/glmm_gamma_dyestuff.json +18 -0
  99. {lme_python-0.1.11 → lme_python-0.2.2}/tests/data/golden_parity_manifest.json +277 -0
  100. lme_python-0.2.2/tests/data/pastes_emmeans.json +15 -0
  101. lme_python-0.2.2/tests/data/pastes_glht_tukey.json +18 -0
  102. lme_python-0.2.2/tests/data/r_edge_case_matrix.json +432 -0
  103. lme_python-0.2.2/tests/data/sleepstudy_confint_profile.json +11 -0
  104. lme_python-0.2.2/tests/data/sleepstudy_confint_profile_vc.json +12 -0
  105. lme_python-0.2.2/tests/data/ssasympoff_nlmer.json +10 -0
  106. lme_python-0.2.2/tests/data/ssasympoff_synthetic.csv +61 -0
  107. lme_python-0.2.2/tests/data/ssasymporig_nlmer.json +10 -0
  108. lme_python-0.2.2/tests/data/ssasymporig_synthetic.csv +61 -0
  109. lme_python-0.2.2/tests/data/ssbiexp_nlmer.json +10 -0
  110. lme_python-0.2.2/tests/data/ssbiexp_synthetic.csv +97 -0
  111. lme_python-0.2.2/tests/data/ssfpl_nlmer.json +10 -0
  112. lme_python-0.2.2/tests/data/ssfpl_synthetic.csv +61 -0
  113. lme_python-0.2.2/tests/data/ssweibull_nlmer.json +10 -0
  114. lme_python-0.2.2/tests/data/ssweibull_synthetic.csv +109 -0
  115. lme_python-0.2.2/tests/generate_nlmm_fixtures.R +354 -0
  116. lme_python-0.2.2/tests/generate_r_edge_case_matrix.R +211 -0
  117. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_anova.rs +2 -0
  118. lme_python-0.2.2/tests/test_bootstrap.rs +331 -0
  119. lme_python-0.2.2/tests/test_confint_profile.rs +198 -0
  120. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_coverage_gaps.rs +2 -0
  121. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_cv.rs +59 -0
  122. lme_python-0.2.2/tests/test_emmeans.rs +166 -0
  123. lme_python-0.2.2/tests/test_explorations.rs +159 -0
  124. lme_python-0.2.2/tests/test_external_timings_artifact.rs +72 -0
  125. lme_python-0.2.2/tests/test_formula.rs +94 -0
  126. lme_python-0.2.2/tests/test_formula_stress.rs +635 -0
  127. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_glmm.rs +96 -4
  128. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_glmm_offset_grouseticks.rs +11 -1
  129. lme_python-0.2.2/tests/test_mcp.rs +182 -0
  130. lme_python-0.2.2/tests/test_nlmm_agq.rs +75 -0
  131. lme_python-0.2.2/tests/test_nlmm_bounds.rs +153 -0
  132. lme_python-0.2.2/tests/test_nlmm_ss_new_means.rs +132 -0
  133. lme_python-0.2.2/tests/test_nlmm_ssasymp_off_orig.rs +76 -0
  134. lme_python-0.2.2/tests/test_r_edge_case_matrix.rs +247 -0
  135. lme_python-0.1.11/.github/workflows/audit.yml +0 -57
  136. lme_python-0.1.11/.github/workflows/ci.yml +0 -228
  137. lme_python-0.1.11/.github/workflows/python-release.yml +0 -169
  138. lme_python-0.1.11/AGENTS.md +0 -195
  139. lme_python-0.1.11/PKG-INFO +0 -15
  140. lme_python-0.1.11/REPO_COMPLETION_BY_AREA.md +0 -102
  141. lme_python-0.1.11/scripts/ast_explorations/test_fiasto.rs +0 -6
  142. lme_python-0.1.11/scripts/ast_explorations/test_fiasto_offset.rs +0 -6
  143. lme_python-0.1.11/src/formula.rs +0 -372
  144. lme_python-0.1.11/tests/generate_nlmm_fixtures.R +0 -124
  145. lme_python-0.1.11/tests/test_bootstrap.rs +0 -131
  146. lme_python-0.1.11/tests/test_formula.rs +0 -11
  147. lme_python-0.1.11/tests/test_formula_stress.rs +0 -316
  148. lme_python-0.1.11/tests/test_nlmm_agq.rs +0 -37
  149. {lme_python-0.1.11 → lme_python-0.2.2}/.JuliaFormatter.toml +0 -0
  150. {lme_python-0.1.11 → lme_python-0.2.2}/.gitignore +0 -0
  151. {lme_python-0.1.11 → lme_python-0.2.2}/LICENSE +0 -0
  152. {lme_python-0.1.11 → lme_python-0.2.2}/LICENSES/Apache-2.0.txt +0 -0
  153. {lme_python-0.1.11 → lme_python-0.2.2}/LICENSES/BSD-3-Clause-OpenBLAS.txt +0 -0
  154. {lme_python-0.1.11 → lme_python-0.2.2}/LICENSES/GPL-2.0-or-later.txt +0 -0
  155. {lme_python-0.1.11 → lme_python-0.2.2}/LICENSES/Intel-Simplified-Software-License.txt +0 -0
  156. {lme_python-0.1.11 → lme_python-0.2.2}/LICENSES/LGPL-2.1-only.txt +0 -0
  157. {lme_python-0.1.11 → lme_python-0.2.2}/RELINKING.md +0 -0
  158. {lme_python-0.1.11 → lme_python-0.2.2}/THIRD_PARTY_NOTICES.md +0 -0
  159. {lme_python-0.1.11 → lme_python-0.2.2}/benches/bench_load_production.rs +0 -0
  160. {lme_python-0.1.11 → lme_python-0.2.2}/benchmarks/fair-rust-julia-reference-2026-07-04.json +0 -0
  161. {lme_python-0.1.11 → lme_python-0.2.2}/benchmarks/fair-rust-julia-reference-2026-07-06.json +0 -0
  162. {lme_python-0.1.11 → lme_python-0.2.2}/benchmarks/fair-rust-julia-reference-2026-07-08.json +0 -0
  163. {lme_python-0.1.11 → lme_python-0.2.2}/benchmarks/fair-rust-julia-reference-2026-07-09-direct-intercept-gram.json +0 -0
  164. {lme_python-0.1.11 → lme_python-0.2.2}/benchmarks/fair-rust-julia-reference-2026-07-09-full-lmm.json +0 -0
  165. {lme_python-0.1.11 → lme_python-0.2.2}/benchmarks/fair-rust-julia-reference-2026-07-09-glmm.json +0 -0
  166. {lme_python-0.1.11 → lme_python-0.2.2}/benchmarks/fair-rust-julia-reference-2026-07-09-large-intercept-setup.json +0 -0
  167. {lme_python-0.1.11 → lme_python-0.2.2}/benchmarks/fair-rust-julia-reference-2026-07-09-large-slopes-linear-cache.json +0 -0
  168. {lme_python-0.1.11 → lme_python-0.2.2}/benchmarks/fair-rust-julia-reference-2026-07-09-large-slopes.json +0 -0
  169. {lme_python-0.1.11 → lme_python-0.2.2}/benchmarks/fair-rust-julia-reference-2026-07-09-sleepstudy-slopes.json +0 -0
  170. {lme_python-0.1.11 → lme_python-0.2.2}/benchmarks/fair-rust-julia-reference-2026-07-09.json +0 -0
  171. {lme_python-0.1.11 → lme_python-0.2.2}/benchmarks/fair-rust-julia-reference-2026-07-10-cold-setup-followup.json +0 -0
  172. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/bench_fair_julia_perf.jl +0 -0
  173. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/bench_fair_rust_julia.rs +0 -0
  174. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/bench_perf_breakdown.rs +0 -0
  175. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/categorical_anova.R +0 -0
  176. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/categorical_anova.jl +0 -0
  177. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/categorical_anova.py +0 -0
  178. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/categorical_anova.rs +0 -0
  179. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/comparison_chart.png +0 -0
  180. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/glmm_cbpp.R +0 -0
  181. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/glmm_cbpp.jl +0 -0
  182. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/glmm_cbpp.py +0 -0
  183. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/glmm_cbpp.rs +0 -0
  184. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/glmm_gaussian.R +0 -0
  185. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/glmm_gaussian.jl +0 -0
  186. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/glmm_gaussian.py +0 -0
  187. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/glmm_gaussian.rs +0 -0
  188. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/glmm_grouseticks.R +0 -0
  189. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/glmm_grouseticks.jl +0 -0
  190. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/glmm_grouseticks.py +0 -0
  191. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/glmm_grouseticks.rs +0 -0
  192. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/lmer_weighted.R +0 -0
  193. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/lmer_weighted.jl +0 -0
  194. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/lmer_weighted.py +0 -0
  195. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/lmer_weighted.rs +0 -0
  196. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/lmm_dyestuff.R +0 -0
  197. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/lmm_dyestuff.jl +0 -0
  198. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/lmm_dyestuff.py +0 -0
  199. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/lmm_dyestuff.rs +0 -0
  200. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/lmm_pastes.R +0 -0
  201. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/lmm_pastes.jl +0 -0
  202. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/lmm_pastes.py +0 -0
  203. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/lmm_pastes.rs +0 -0
  204. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/lmm_penicillin.R +0 -0
  205. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/lmm_penicillin.jl +0 -0
  206. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/lmm_penicillin.py +0 -0
  207. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/lmm_penicillin.rs +0 -0
  208. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/nlmm_sspower.R +0 -0
  209. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/parity/glmm_offset.R +0 -0
  210. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/parity/glmm_offset.jl +0 -0
  211. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/parity/glmm_probit.R +0 -0
  212. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/parity/glmm_probit.jl +0 -0
  213. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/parity/glmm_weighted.R +0 -0
  214. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/parity/glmm_weighted.jl +0 -0
  215. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/parity/parity_r_setup.R +0 -0
  216. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/parity/sleepstudy_offset.R +0 -0
  217. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/parity/sleepstudy_offset.jl +0 -0
  218. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/parity_export.rs +0 -0
  219. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/r_setup.R +0 -0
  220. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/sleepstudy.R +0 -0
  221. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/sleepstudy.jl +0 -0
  222. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/sleepstudy.py +0 -0
  223. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/sleepstudy.rs +0 -0
  224. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/sleepstudy_ml.R +0 -0
  225. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/sleepstudy_ml.jl +0 -0
  226. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/sleepstudy_ml.py +0 -0
  227. {lme_python-0.1.11 → lme_python-0.2.2}/comparisons/sleepstudy_ml.rs +0 -0
  228. {lme_python-0.1.11 → lme_python-0.2.2}/docs/benchmarks/app.js +0 -0
  229. {lme_python-0.1.11 → lme_python-0.2.2}/docs/benchmarks/index.html +0 -0
  230. {lme_python-0.1.11 → lme_python-0.2.2}/docs/benchmarks/styles.css +0 -0
  231. {lme_python-0.1.11 → lme_python-0.2.2}/docs/index.html +0 -0
  232. {lme_python-0.1.11 → lme_python-0.2.2}/examples/batch_sspower_cpu.rs +0 -0
  233. {lme_python-0.1.11 → lme_python-0.2.2}/examples/nlmm_fixture_dump.rs +0 -0
  234. {lme_python-0.1.11 → lme_python-0.2.2}/lefthook.yml +0 -0
  235. {lme_python-0.1.11 → lme_python-0.2.2}/legal/dependency-license-exceptions.json +0 -0
  236. {lme_python-0.1.11 → lme_python-0.2.2}/mise.toml +0 -0
  237. {lme_python-0.1.11 → lme_python-0.2.2}/python/examples/glmer_cbpp.py +0 -0
  238. {lme_python-0.1.11 → lme_python-0.2.2}/python/examples/glmer_grouseticks.py +0 -0
  239. {lme_python-0.1.11 → lme_python-0.2.2}/python/examples/lm_basics.py +0 -0
  240. {lme_python-0.1.11 → lme_python-0.2.2}/python/examples/lmer_sleepstudy.py +0 -0
  241. {lme_python-0.1.11 → lme_python-0.2.2}/python/examples/model_comparison.py +0 -0
  242. {lme_python-0.1.11 → lme_python-0.2.2}/python/examples/plotting_demo/.gitignore +0 -0
  243. {lme_python-0.1.11 → lme_python-0.2.2}/python/examples/plotting_demo/README.md +0 -0
  244. {lme_python-0.1.11 → lme_python-0.2.2}/python/examples/plotting_demo/compare_plots.py +0 -0
  245. {lme_python-0.1.11 → lme_python-0.2.2}/python/examples/plotting_demo/figure_specs.py +0 -0
  246. {lme_python-0.1.11 → lme_python-0.2.2}/python/examples/plotting_demo/find_rscript.py +0 -0
  247. {lme_python-0.1.11 → lme_python-0.2.2}/python/examples/plotting_demo/numeric_overlay.py +0 -0
  248. {lme_python-0.1.11 → lme_python-0.2.2}/python/examples/plotting_demo/paths.py +0 -0
  249. {lme_python-0.1.11 → lme_python-0.2.2}/python/examples/plotting_demo/plot_demo.py +0 -0
  250. {lme_python-0.1.11 → lme_python-0.2.2}/python/examples/plotting_demo/plot_r.R +0 -0
  251. {lme_python-0.1.11 → lme_python-0.2.2}/python/examples/plotting_demo/run_all.py +0 -0
  252. {lme_python-0.1.11 → lme_python-0.2.2}/python/examples/verification_project/README.md +0 -0
  253. {lme_python-0.1.11 → lme_python-0.2.2}/python/examples/verification_project/conftest.py +0 -0
  254. {lme_python-0.1.11 → lme_python-0.2.2}/python/examples/verification_project/paths.py +0 -0
  255. {lme_python-0.1.11 → lme_python-0.2.2}/python/examples/verification_project/test_parity.py +0 -0
  256. {lme_python-0.1.11 → lme_python-0.2.2}/python/tests/test_basic.py +0 -0
  257. {lme_python-0.1.11 → lme_python-0.2.2}/python/tests/test_dataframe_inputs.py +0 -0
  258. {lme_python-0.1.11 → lme_python-0.2.2}/python/tests/test_golden_parity.py +0 -0
  259. {lme_python-0.1.11 → lme_python-0.2.2}/python/tests/test_simulate_scale.py +0 -0
  260. {lme_python-0.1.11 → lme_python-0.2.2}/python/tests/test_wheel_notices.py +0 -0
  261. {lme_python-0.1.11 → lme_python-0.2.2}/python/uv.lock +0 -0
  262. {lme_python-0.1.11 → lme_python-0.2.2}/scripts/build_benchmark_site.py +0 -0
  263. {lme_python-0.1.11 → lme_python-0.2.2}/scripts/ci/check_legal_compliance.py +0 -0
  264. {lme_python-0.1.11 → lme_python-0.2.2}/scripts/ci/julia_format.jl +0 -0
  265. {lme_python-0.1.11 → lme_python-0.2.2}/scripts/ci/package_wheel_notices.py +0 -0
  266. {lme_python-0.1.11 → lme_python-0.2.2}/scripts/ci/r_format.R +0 -0
  267. {lme_python-0.1.11 → lme_python-0.2.2}/scripts/ci/run.sh +0 -0
  268. {lme_python-0.1.11 → lme_python-0.2.2}/scripts/dump_dyestuff.R +0 -0
  269. {lme_python-0.1.11 → lme_python-0.2.2}/scripts/dump_pastes.R +0 -0
  270. {lme_python-0.1.11 → lme_python-0.2.2}/scripts/local_ci.ps1 +0 -0
  271. {lme_python-0.1.11 → lme_python-0.2.2}/scripts/local_ci.sh +0 -0
  272. {lme_python-0.1.11 → lme_python-0.2.2}/scripts/make_penicillin_csv.py +0 -0
  273. {lme_python-0.1.11 → lme_python-0.2.2}/scripts/plot_comparisons.py +0 -0
  274. {lme_python-0.1.11 → lme_python-0.2.2}/scripts/run_cross_language_benchmarks.py +0 -0
  275. {lme_python-0.1.11 → lme_python-0.2.2}/scripts/run_perf_breakdown.py +0 -0
  276. {lme_python-0.1.11 → lme_python-0.2.2}/scripts/sync_github_repo_metadata.py +0 -0
  277. {lme_python-0.1.11 → lme_python-0.2.2}/scripts/verify_cross_language_parity.py +0 -0
  278. {lme_python-0.1.11 → lme_python-0.2.2}/src/anova.rs +0 -0
  279. {lme_python-0.1.11 → lme_python-0.2.2}/src/anova_contrasts.rs +0 -0
  280. {lme_python-0.1.11 → lme_python-0.2.2}/src/ddf.rs +0 -0
  281. {lme_python-0.1.11 → lme_python-0.2.2}/src/kr_modcomp.rs +0 -0
  282. {lme_python-0.1.11 → lme_python-0.2.2}/src/kr_vcov_adj.rs +0 -0
  283. {lme_python-0.1.11 → lme_python-0.2.2}/src/nlmm/predict.rs +0 -0
  284. {lme_python-0.1.11 → lme_python-0.2.2}/src/nlmm/re_cov.rs +0 -0
  285. {lme_python-0.1.11 → lme_python-0.2.2}/src/nlmm/ssasymp.rs +0 -0
  286. {lme_python-0.1.11 → lme_python-0.2.2}/src/nlmm/ssgompertz.rs +0 -0
  287. {lme_python-0.1.11 → lme_python-0.2.2}/src/nlmm/sslogis.rs +0 -0
  288. {lme_python-0.1.11 → lme_python-0.2.2}/src/nlmm/ssmicmen.rs +0 -0
  289. {lme_python-0.1.11 → lme_python-0.2.2}/src/nlmm/sspower.rs +0 -0
  290. {lme_python-0.1.11 → lme_python-0.2.2}/src/quadrature.rs +0 -0
  291. {lme_python-0.1.11 → lme_python-0.2.2}/tests/categorical_anova_test.rs +0 -0
  292. {lme_python-0.1.11 → lme_python-0.2.2}/tests/data/cbpp_binary.csv +0 -0
  293. {lme_python-0.1.11 → lme_python-0.2.2}/tests/data/cbpp_binary_weighted.csv +0 -0
  294. {lme_python-0.1.11 → lme_python-0.2.2}/tests/data/dyestuff.csv +0 -0
  295. {lme_python-0.1.11 → lme_python-0.2.2}/tests/data/glmm_binomial.json +0 -0
  296. {lme_python-0.1.11 → lme_python-0.2.2}/tests/data/glmm_binomial_probit.json +0 -0
  297. {lme_python-0.1.11 → lme_python-0.2.2}/tests/data/glmm_binomial_weighted.json +0 -0
  298. {lme_python-0.1.11 → lme_python-0.2.2}/tests/data/glmm_poisson.json +0 -0
  299. {lme_python-0.1.11 → lme_python-0.2.2}/tests/data/glmm_poisson_offset.json +0 -0
  300. {lme_python-0.1.11 → lme_python-0.2.2}/tests/data/grouseticks.csv +0 -0
  301. {lme_python-0.1.11 → lme_python-0.2.2}/tests/data/intercept_only.json +0 -0
  302. {lme_python-0.1.11 → lme_python-0.2.2}/tests/data/mock_crossed.json +0 -0
  303. {lme_python-0.1.11 → lme_python-0.2.2}/tests/data/mock_ml.json +0 -0
  304. {lme_python-0.1.11 → lme_python-0.2.2}/tests/data/orange.csv +0 -0
  305. {lme_python-0.1.11 → lme_python-0.2.2}/tests/data/orange_nlmer.json +0 -0
  306. {lme_python-0.1.11 → lme_python-0.2.2}/tests/data/pastes.csv +0 -0
  307. {lme_python-0.1.11 → lme_python-0.2.2}/tests/data/pastes_cask_reml.json +0 -0
  308. {lme_python-0.1.11 → lme_python-0.2.2}/tests/data/penicillin.csv +0 -0
  309. {lme_python-0.1.11 → lme_python-0.2.2}/tests/data/penicillin.json +0 -0
  310. {lme_python-0.1.11 → lme_python-0.2.2}/tests/data/random_slopes.json +0 -0
  311. {lme_python-0.1.11 → lme_python-0.2.2}/tests/data/sleepstudy.csv +0 -0
  312. {lme_python-0.1.11 → lme_python-0.2.2}/tests/data/sleepstudy_offset_reml.json +0 -0
  313. {lme_python-0.1.11 → lme_python-0.2.2}/tests/data/ssasymp_synthetic.csv +0 -0
  314. {lme_python-0.1.11 → lme_python-0.2.2}/tests/data/ssfol_nlmer.json +0 -0
  315. {lme_python-0.1.11 → lme_python-0.2.2}/tests/data/ssgompertz_nlmer.json +0 -0
  316. {lme_python-0.1.11 → lme_python-0.2.2}/tests/data/ssgompertz_synthetic.csv +0 -0
  317. {lme_python-0.1.11 → lme_python-0.2.2}/tests/data/ssmicmen_nlmer.json +0 -0
  318. {lme_python-0.1.11 → lme_python-0.2.2}/tests/data/ssmicmen_synthetic.csv +0 -0
  319. {lme_python-0.1.11 → lme_python-0.2.2}/tests/data/sspower_nlmer.json +0 -0
  320. {lme_python-0.1.11 → lme_python-0.2.2}/tests/data/sspower_synthetic.csv +0 -0
  321. {lme_python-0.1.11 → lme_python-0.2.2}/tests/gen_nlmm_extras.R +0 -0
  322. {lme_python-0.1.11 → lme_python-0.2.2}/tests/generate_mock_data.py +0 -0
  323. {lme_python-0.1.11 → lme_python-0.2.2}/tests/generate_test_data.R +0 -0
  324. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_anova_types.rs +0 -0
  325. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_conditional_real.rs +0 -0
  326. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_confint_simulate.rs +0 -0
  327. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_contrast.rs +0 -0
  328. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_coverage_edge_cases.rs +0 -0
  329. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_crossed_mock.rs +0 -0
  330. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_e2e_lmer.rs +0 -0
  331. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_edge_cases.rs +0 -0
  332. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_errors.rs +0 -0
  333. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_failure_modes.rs +0 -0
  334. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_gaps.rs +0 -0
  335. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_glmm_links.rs +0 -0
  336. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_glmm_weighted.rs +0 -0
  337. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_golden_parity.rs +0 -0
  338. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_intercept_only.rs +0 -0
  339. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_kenward_roger.rs +0 -0
  340. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_kr_modcomp_pastes.rs +0 -0
  341. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_ml_optimization.rs +0 -0
  342. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_nlmm_custom_mean.rs +0 -0
  343. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_nlmm_orange.rs +0 -0
  344. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_nlmm_orange_multi_re.rs +0 -0
  345. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_nlmm_self_start.rs +0 -0
  346. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_nlmm_ssasymp.rs +0 -0
  347. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_nlmm_ssfol.rs +0 -0
  348. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_nlmm_ssmicmen.rs +0 -0
  349. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_nlmm_sspower.rs +0 -0
  350. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_no_intercept.rs +0 -0
  351. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_numerical_parity.rs +0 -0
  352. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_predict.rs +0 -0
  353. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_production_load.rs +0 -0
  354. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_random_slopes.rs +0 -0
  355. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_robust.rs +0 -0
  356. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_sandwich_math.R +0 -0
  357. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_satterthwaite.rs +0 -0
  358. {lme_python-0.1.11 → lme_python-0.2.2}/tests/test_statistical_identities.rs +0 -0
@@ -0,0 +1,10 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: github-actions
4
+ directory: /
5
+ schedule:
6
+ interval: weekly
7
+ groups:
8
+ github-actions:
9
+ patterns:
10
+ - "*"
@@ -0,0 +1,62 @@
1
+ name: Security audit
2
+
3
+ # Release CI calls this workflow as a required publication gate.
4
+ # A weekly schedule and workflow_dispatch provide continuous/on-demand audits.
5
+
6
+ on:
7
+ workflow_call:
8
+ workflow_dispatch:
9
+ schedule:
10
+ - cron: "17 4 * * 1"
11
+
12
+ permissions:
13
+ contents: read
14
+
15
+ concurrency:
16
+ group: audit-${{ github.workflow }}-${{ github.ref }}
17
+ cancel-in-progress: true
18
+
19
+ jobs:
20
+ audit:
21
+ name: cargo audit
22
+ runs-on: ubuntu-latest
23
+ steps:
24
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
25
+
26
+ - uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable
27
+ with:
28
+ toolchain: stable
29
+
30
+ - name: Install cargo-audit
31
+ uses: taiki-e/install-action@7f4eb899022d8fe70b20c4f3de697aa85c309026 # v2
32
+ with:
33
+ tool: cargo-audit@0.22.1
34
+
35
+ - name: Run cargo audit (root)
36
+ # paste is required by argmin 0.11; RUSTSEC-2024-0436 is informational
37
+ # and has no patched argmin release. Deny every other warning.
38
+ run: cargo audit --deny warnings --ignore RUSTSEC-2024-0436
39
+
40
+ - name: Run cargo audit (python/)
41
+ working-directory: python
42
+ run: cargo audit --deny warnings --ignore RUSTSEC-2024-0436
43
+
44
+ pip-audit:
45
+ name: pip-audit (uv.lock)
46
+ runs-on: ubuntu-latest
47
+ steps:
48
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
49
+
50
+ - name: Set up uv
51
+ uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
52
+ with:
53
+ python-version: "3.11"
54
+ enable-cache: true
55
+ cache-dependency-glob: "python/uv.lock"
56
+
57
+ - name: pip-audit
58
+ working-directory: python
59
+ run: |
60
+ set -euo pipefail
61
+ uv sync --extra dev --no-install-project
62
+ uv run --no-sync pip-audit
@@ -29,15 +29,17 @@ jobs:
29
29
  name: Criterion Benchmarks
30
30
  runs-on: ubuntu-latest
31
31
  steps:
32
- - uses: actions/checkout@v6
32
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
33
33
 
34
- - uses: dtolnay/rust-toolchain@stable
34
+ - uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable
35
+ with:
36
+ toolchain: stable
35
37
 
36
38
  - name: Install OpenBLAS
37
39
  run: sudo apt-get update && sudo apt-get install -y libopenblas-dev
38
40
 
39
41
  - name: Cache cargo registry and build outputs
40
- uses: actions/cache@v5
42
+ uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
41
43
  with:
42
44
  path: |
43
45
  ~/.cargo/registry
@@ -55,7 +57,7 @@ jobs:
55
57
  tar -czf "benchmark-results/criterion-${{ github.sha }}.tar.gz" target/criterion
56
58
 
57
59
  - name: Upload Criterion artifact
58
- uses: actions/upload-artifact@v7
60
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
59
61
  with:
60
62
  name: criterion-${{ github.sha }}
61
63
  path: benchmark-results/criterion-${{ github.sha }}.tar.gz
@@ -82,11 +84,13 @@ jobs:
82
84
  BENCH_REPEATS: ${{ github.event_name == 'workflow_dispatch' && inputs.repeats || '3' }}
83
85
  R_LIBS_USER: ${{ github.workspace }}/.r-lib
84
86
  steps:
85
- - uses: actions/checkout@v6
87
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
86
88
 
87
- - uses: dtolnay/rust-toolchain@stable
89
+ - uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable
90
+ with:
91
+ toolchain: stable
88
92
 
89
- - uses: actions/setup-python@v6
93
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
90
94
  with:
91
95
  python-version: "3.11"
92
96
 
@@ -101,7 +105,7 @@ jobs:
101
105
  julia --version
102
106
 
103
107
  - name: Cache cargo registry and build outputs
104
- uses: actions/cache@v5
108
+ uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
105
109
  with:
106
110
  path: |
107
111
  ~/.cargo/registry
@@ -157,9 +161,10 @@ jobs:
157
161
 
158
162
  - name: Upload cross-language artifact
159
163
  if: always()
160
- uses: actions/upload-artifact@v7
164
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
161
165
  with:
162
166
  name: cross-language-${{ github.sha }}
167
+ if-no-files-found: ignore
163
168
  path: |
164
169
  benchmark-results/cross-language-${{ github.sha }}.json
165
170
  benchmark-results/fair-rust-julia-${{ github.sha }}.json
@@ -176,9 +181,13 @@ jobs:
176
181
  gh release create "${GITHUB_REF_NAME}" --title "${GITHUB_REF_NAME}"
177
182
  fi
178
183
  }
179
- gh release upload "${GITHUB_REF_NAME}" "benchmark-results/cross-language-${{ github.sha }}.json" --clobber
180
- if [ -f "benchmark-results/fair-rust-julia-${{ github.sha }}.json" ]; then
181
- gh release upload "${GITHUB_REF_NAME}" "benchmark-results/fair-rust-julia-${{ github.sha }}.json" --clobber
184
+ cross_json="benchmark-results/cross-language-${{ github.sha }}.json"
185
+ fair_json="benchmark-results/fair-rust-julia-${{ github.sha }}.json"
186
+ if [ -f "$cross_json" ]; then
187
+ gh release upload "${GITHUB_REF_NAME}" "$cross_json" --clobber
188
+ fi
189
+ if [ -f "$fair_json" ]; then
190
+ gh release upload "${GITHUB_REF_NAME}" "$fair_json" --clobber
182
191
  fi
183
192
 
184
193
  - name: Fail if cross-language benchmarks failed
@@ -0,0 +1,121 @@
1
+ name: Prime Rust caches
2
+
3
+ # PR caches are scoped to a single pull request. Keep trusted default-branch
4
+ # dependency caches warm so new PRs do not start by rebuilding Polars and BLAS.
5
+
6
+ on:
7
+ push:
8
+ branches:
9
+ - master
10
+ paths:
11
+ - "Cargo.toml"
12
+ - "Cargo.lock"
13
+ - "python/Cargo.toml"
14
+ - "python/Cargo.lock"
15
+ - "rust-toolchain"
16
+ - "rust-toolchain.toml"
17
+ - ".cargo/**"
18
+ - ".github/workflows/ci.yml"
19
+ - ".github/workflows/cache-prime.yml"
20
+ schedule:
21
+ - cron: "17 3 * * 1"
22
+ workflow_dispatch:
23
+
24
+ permissions:
25
+ contents: read
26
+
27
+ concurrency:
28
+ group: cache-prime-${{ github.ref }}
29
+ cancel-in-progress: true
30
+
31
+ env:
32
+ CARGO_TERM_COLOR: always
33
+ CARGO_INCREMENTAL: "0"
34
+ CARGO_PROFILE_DEV_DEBUG: "0"
35
+ CARGO_PROFILE_TEST_DEBUG: "0"
36
+
37
+ jobs:
38
+ rust-dependencies:
39
+ name: Rust dependencies (${{ matrix.os }})
40
+ runs-on: ${{ matrix.os }}
41
+ strategy:
42
+ fail-fast: false
43
+ matrix:
44
+ os: [ubuntu-latest, windows-latest, macos-latest]
45
+ steps:
46
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
47
+ - uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable
48
+ with:
49
+ toolchain: stable
50
+ - name: Install OpenBLAS (Ubuntu)
51
+ if: matrix.os == 'ubuntu-latest'
52
+ run: sudo apt-get update && sudo apt-get install -y libopenblas-dev
53
+ - name: Set OpenBLAS target (macOS)
54
+ if: matrix.os == 'macos-latest'
55
+ run: echo "OPENBLAS_TARGET=ARMV8" >> "$GITHUB_ENV"
56
+ - name: Cache Rust dependencies
57
+ uses: Swatinem/rust-cache@a45951ff880207c249adf57334cf2e9bd81d6e1e # v2
58
+ with:
59
+ shared-key: ci-v2-${{ runner.os }}-rust-test
60
+ cache-workspace-crates: ${{ runner.os != 'Linux' }}
61
+ - name: Compile canonical test dependencies
62
+ if: matrix.os == 'ubuntu-latest'
63
+ run: cargo test --locked --no-run
64
+ - name: Compile consolidated test dependencies
65
+ if: matrix.os != 'ubuntu-latest'
66
+ run: python scripts/ci/lme_ci.py consolidated-test --no-run
67
+
68
+ production-dependencies:
69
+ name: Production-load dependencies (ubuntu)
70
+ runs-on: ubuntu-latest
71
+ steps:
72
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
73
+ - uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable
74
+ with:
75
+ toolchain: stable
76
+ - name: Install OpenBLAS
77
+ run: sudo apt-get update && sudo apt-get install -y libopenblas-dev
78
+ - name: Cache production-load Rust dependencies
79
+ uses: Swatinem/rust-cache@a45951ff880207c249adf57334cf2e9bd81d6e1e # v2
80
+ with:
81
+ shared-key: ci-v2-${{ runner.os }}-rust-release
82
+ cache-workspace-crates: true
83
+ - name: Compile production-load dependencies
84
+ run: cargo test --release --locked --test test_production_load --no-run
85
+
86
+ python-dependencies:
87
+ name: Python dependencies (${{ matrix.os }})
88
+ runs-on: ${{ matrix.os }}
89
+ strategy:
90
+ fail-fast: false
91
+ matrix:
92
+ os: [ubuntu-latest, windows-latest, macos-latest]
93
+ steps:
94
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
95
+ - uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable
96
+ with:
97
+ toolchain: stable
98
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
99
+ with:
100
+ python-version: "3.11"
101
+ - name: Install OpenBLAS (Ubuntu)
102
+ if: matrix.os == 'ubuntu-latest'
103
+ run: sudo apt-get update && sudo apt-get install -y libopenblas-dev
104
+ - name: Set OpenBLAS target (macOS)
105
+ if: matrix.os == 'macos-latest'
106
+ run: echo "OPENBLAS_TARGET=ARMV8" >> "$GITHUB_ENV"
107
+ - name: Cache Python Rust dependencies
108
+ uses: Swatinem/rust-cache@a45951ff880207c249adf57334cf2e9bd81d6e1e # v2
109
+ with:
110
+ shared-key: ci-${{ runner.os }}-python
111
+ workspaces: python -> target
112
+ - name: Compile Python binding dependencies
113
+ if: matrix.os != 'macos-latest'
114
+ env:
115
+ PYO3_PYTHON: python
116
+ run: cargo build --release --manifest-path python/Cargo.toml
117
+ - name: Compile Python binding dependencies (macOS)
118
+ if: matrix.os == 'macos-latest'
119
+ uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # v1
120
+ with:
121
+ args: --release --out python/dist --manifest-path python/Cargo.toml
@@ -0,0 +1,267 @@
1
+ name: CI
2
+
3
+ # Automatic runs: pull requests and v* release tags. Use workflow_dispatch for
4
+ # an intentional full check on any branch (Actions → CI → Run workflow).
5
+
6
+ on:
7
+ pull_request:
8
+ push:
9
+ tags:
10
+ - "v*"
11
+ workflow_dispatch:
12
+
13
+ permissions:
14
+ contents: read
15
+
16
+ concurrency:
17
+ group: ci-${{ github.workflow }}-${{ github.ref }}
18
+ cancel-in-progress: true
19
+
20
+ env:
21
+ CARGO_TERM_COLOR: always
22
+ CARGO_INCREMENTAL: "0"
23
+ CARGO_PROFILE_DEV_DEBUG: "0"
24
+ CARGO_PROFILE_TEST_DEBUG: "0"
25
+
26
+ jobs:
27
+ release-policy:
28
+ name: Release policy checks
29
+ runs-on: ubuntu-latest
30
+ steps:
31
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
32
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
33
+ with:
34
+ python-version: "3.11"
35
+ - name: Validate legal notices and provenance
36
+ run: python3 scripts/ci/lme_ci.py legal
37
+ - name: Validate Markdown links
38
+ run: python3 scripts/ci/lme_ci.py docs-links
39
+ - name: Validate completion score claims
40
+ run: python3 scripts/ci/lme_ci.py completion-check
41
+
42
+ security-audit:
43
+ name: Dependency security audit
44
+ permissions:
45
+ contents: read
46
+ uses: ./.github/workflows/audit.yml
47
+
48
+ rust-ubuntu:
49
+ name: Rust validation (ubuntu)
50
+ runs-on: ubuntu-latest
51
+ steps:
52
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
53
+ - uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable
54
+ with:
55
+ toolchain: stable
56
+ - name: Install OpenBLAS
57
+ run: sudo apt-get update && sudo apt-get install -y libopenblas-dev
58
+ - name: Cache Rust dependencies
59
+ uses: Swatinem/rust-cache@a45951ff880207c249adf57334cf2e9bd81d6e1e # v2
60
+ with:
61
+ shared-key: ci-v2-${{ runner.os }}-rust-test
62
+ save-if: ${{ github.event_name == 'pull_request' || github.ref == 'refs/heads/master' }}
63
+ - name: rustfmt --check
64
+ id: rustfmt
65
+ continue-on-error: true
66
+ run: python3 scripts/ci/lme_ci.py fmt-check
67
+ - name: clippy
68
+ id: clippy
69
+ continue-on-error: true
70
+ run: python3 scripts/ci/lme_ci.py clippy
71
+ - name: cargo check --workspace --all-targets
72
+ id: check
73
+ continue-on-error: true
74
+ run: python3 scripts/ci/lme_ci.py check
75
+ - name: Run tests
76
+ id: tests
77
+ continue-on-error: true
78
+ run: python3 scripts/ci/lme_ci.py build-test
79
+ - name: Run doctests
80
+ id: doctests
81
+ continue-on-error: true
82
+ run: python3 scripts/ci/lme_ci.py doctest
83
+ - name: Build documentation
84
+ id: docs
85
+ continue-on-error: true
86
+ run: python3 scripts/ci/lme_ci.py doc
87
+ - name: Report Rust validation failures
88
+ if: >-
89
+ ${{ !cancelled() && (
90
+ steps.rustfmt.outcome == 'failure' ||
91
+ steps.clippy.outcome == 'failure' ||
92
+ steps.check.outcome == 'failure' ||
93
+ steps.tests.outcome == 'failure' ||
94
+ steps.doctests.outcome == 'failure' ||
95
+ steps.docs.outcome == 'failure'
96
+ ) }}
97
+ run: exit 1
98
+
99
+ test:
100
+ name: Test (${{ matrix.os }})
101
+ runs-on: ${{ matrix.os }}
102
+ strategy:
103
+ fail-fast: false
104
+ matrix:
105
+ os: [windows-latest, macos-latest]
106
+
107
+ steps:
108
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
109
+
110
+ - name: Install Rust toolchain
111
+ uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable
112
+ with:
113
+ toolchain: stable
114
+
115
+ - name: Cache Rust dependencies
116
+ uses: Swatinem/rust-cache@a45951ff880207c249adf57334cf2e9bd81d6e1e # v2
117
+ with:
118
+ shared-key: ci-v2-${{ runner.os }}-rust-test
119
+ cache-workspace-crates: true
120
+ save-if: ${{ github.event_name == 'pull_request' || github.ref == 'refs/heads/master' }}
121
+
122
+ - name: Set OpenBLAS target (macOS)
123
+ if: matrix.os == 'macos-latest'
124
+ run: echo "OPENBLAS_TARGET=ARMV8" >> "$GITHUB_ENV"
125
+
126
+ - name: Run tests
127
+ run: python scripts/ci/lme_ci.py consolidated-test
128
+
129
+ production-load:
130
+ name: Production load & perf gates (ubuntu, release)
131
+ runs-on: ubuntu-latest
132
+ steps:
133
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
134
+
135
+ - name: Install Rust toolchain
136
+ uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable
137
+ with:
138
+ toolchain: stable
139
+
140
+ - name: Install OpenBLAS (Ubuntu)
141
+ run: sudo apt-get update && sudo apt-get install -y libopenblas-dev
142
+
143
+ - name: Restore Rust dependencies
144
+ uses: Swatinem/rust-cache@a45951ff880207c249adf57334cf2e9bd81d6e1e # v2
145
+ with:
146
+ shared-key: ci-v2-${{ runner.os }}-rust-release
147
+ cache-workspace-crates: true
148
+ save-if: ${{ github.event_name == 'pull_request' || github.ref == 'refs/heads/master' }}
149
+
150
+ - name: Production load tests (smoke + release wall-clock gates)
151
+ run: cargo test --release --locked --verbose --test test_production_load
152
+
153
+ - name: Heavy production load tests (ignored)
154
+ if: github.event_name != 'pull_request'
155
+ run: cargo test --release --locked --verbose --test test_production_load -- --ignored --test-threads=1
156
+
157
+ python-bindings-versions:
158
+ name: Python ${{ matrix.python-version }} (ubuntu)
159
+ runs-on: ubuntu-latest
160
+ strategy:
161
+ fail-fast: false
162
+ matrix:
163
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
164
+ steps:
165
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
166
+ - uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable
167
+ with:
168
+ toolchain: stable
169
+ - name: Install OpenBLAS
170
+ run: sudo apt-get update && sudo apt-get install -y libopenblas-dev
171
+ - name: Cache Python Rust dependencies
172
+ uses: Swatinem/rust-cache@a45951ff880207c249adf57334cf2e9bd81d6e1e # v2
173
+ with:
174
+ shared-key: ci-${{ runner.os }}-python
175
+ workspaces: python -> target
176
+ save-if: ${{ matrix.python-version == '3.11' && (github.event_name == 'pull_request' || github.ref == 'refs/heads/master') }}
177
+ - name: Set up uv
178
+ uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
179
+ with:
180
+ python-version: ${{ matrix.python-version }}
181
+ enable-cache: true
182
+ cache-dependency-glob: "python/uv.lock"
183
+
184
+ - name: Python bindings (canonical editable identity + isolated wheel)
185
+ if: matrix.python-version == '3.11'
186
+ run: python scripts/ci/lme_ci.py python --python-version ${{ matrix.python-version }} --examples
187
+
188
+ - name: Python bindings (isolated wheel compatibility)
189
+ if: matrix.python-version != '3.11'
190
+ run: python scripts/ci/lme_ci.py python --python-version ${{ matrix.python-version }} --wheel-only
191
+
192
+ python-bindings-os:
193
+ name: Python 3.11 (${{ matrix.os }})
194
+ runs-on: ${{ matrix.os }}
195
+ strategy:
196
+ fail-fast: false
197
+ matrix:
198
+ os: [windows-latest, macos-latest]
199
+ steps:
200
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
201
+ - uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable
202
+ with:
203
+ toolchain: stable
204
+ - name: Set OpenBLAS target (macOS)
205
+ if: matrix.os == 'macos-latest'
206
+ run: echo "OPENBLAS_TARGET=ARMV8" >> "$GITHUB_ENV"
207
+ - name: Cache Python Rust dependencies
208
+ uses: Swatinem/rust-cache@a45951ff880207c249adf57334cf2e9bd81d6e1e # v2
209
+ with:
210
+ shared-key: ci-${{ runner.os }}-python
211
+ workspaces: python -> target
212
+ save-if: ${{ github.event_name == 'pull_request' || github.ref == 'refs/heads/master' }}
213
+ - name: Set up uv
214
+ uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
215
+ with:
216
+ python-version: "3.11"
217
+ enable-cache: true
218
+ cache-dependency-glob: "python/uv.lock"
219
+ - name: Python bindings (isolated wheel OS compatibility)
220
+ run: python scripts/ci/lme_ci.py python --python-version 3.11 --wheel-only --examples
221
+
222
+ publish-crate:
223
+ name: Publish Rust crate after CI
224
+ if: startsWith(github.ref, 'refs/tags/v')
225
+ needs:
226
+ - release-policy
227
+ - security-audit
228
+ - rust-ubuntu
229
+ - test
230
+ - production-load
231
+ - python-bindings-versions
232
+ - python-bindings-os
233
+ permissions:
234
+ contents: read
235
+ uses: ./.github/workflows/crate-publish-dry-run.yml
236
+ with:
237
+ publish: true
238
+ secrets: inherit
239
+
240
+ publish-python:
241
+ name: Dispatch Python release after CI
242
+ if: startsWith(github.ref, 'refs/tags/v')
243
+ needs:
244
+ - release-policy
245
+ - security-audit
246
+ - rust-ubuntu
247
+ - test
248
+ - production-load
249
+ - python-bindings-versions
250
+ - python-bindings-os
251
+ permissions:
252
+ actions: write
253
+ contents: read
254
+ runs-on: ubuntu-latest
255
+ steps:
256
+ - name: Dispatch verified Python release
257
+ env:
258
+ GH_TOKEN: ${{ github.token }}
259
+ RELEASE_SHA: ${{ github.sha }}
260
+ RELEASE_TAG: ${{ github.ref_name }}
261
+ run: |
262
+ gh workflow run python-release.yml \
263
+ --repo "${GITHUB_REPOSITORY}" \
264
+ --ref master \
265
+ -f release_tag="${RELEASE_TAG}" \
266
+ -f release_sha="${RELEASE_SHA}" \
267
+ -f publish=true
@@ -1,12 +1,16 @@
1
1
  name: Publish Rust crate
2
2
 
3
- # Publishes to crates.io only on v* tag pushes. Manual dispatch validates with
4
- # cargo publish --dry-run (no registry token required).
3
+ # CI calls this workflow after every release-tag validation job succeeds.
4
+ # Manual dispatch validates with cargo publish --dry-run and never publishes.
5
5
 
6
6
  on:
7
- push:
8
- tags:
9
- - "v*"
7
+ workflow_call:
8
+ inputs:
9
+ publish:
10
+ description: Publish the validated release tag to crates.io
11
+ required: false
12
+ type: boolean
13
+ default: false
10
14
  workflow_dispatch:
11
15
 
12
16
  permissions:
@@ -21,16 +25,17 @@ jobs:
21
25
  name: cargo publish
22
26
  runs-on: ubuntu-latest
23
27
  steps:
24
- - uses: actions/checkout@v6
28
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
25
29
 
26
- - uses: dtolnay/rust-toolchain@stable
30
+ - uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable
31
+ with:
32
+ toolchain: stable
27
33
 
28
34
  - name: Validate crate package (dry run)
29
- if: github.event_name == 'workflow_dispatch'
30
35
  run: cargo publish --dry-run --locked
31
36
 
32
37
  - name: Publish root crate
33
- if: startsWith(github.ref, 'refs/tags/')
38
+ if: inputs.publish && startsWith(github.ref, 'refs/tags/v')
34
39
  env:
35
40
  CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
36
41
  run: |
@@ -1,8 +1,17 @@
1
- # Manual libFuzzer smoke (long compile + short run). Trigger from the Actions tab.
2
- name: Fuzz (manual)
1
+ # Weekly and manually dispatched libFuzzer smoke.
2
+ name: Fuzz smoke
3
3
 
4
4
  on:
5
5
  workflow_dispatch:
6
+ schedule:
7
+ - cron: "43 3 * * 0"
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ concurrency:
13
+ group: fuzz-${{ github.workflow }}-${{ github.ref }}
14
+ cancel-in-progress: true
6
15
 
7
16
  jobs:
8
17
  libfuzzer-smoke:
@@ -13,14 +22,16 @@ jobs:
13
22
  working-directory: fuzz
14
23
 
15
24
  steps:
16
- - uses: actions/checkout@v4
25
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
17
26
 
18
- - uses: dtolnay/rust-toolchain@nightly
27
+ - uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # nightly
28
+ with:
29
+ toolchain: nightly
19
30
 
20
31
  - name: Install cargo-fuzz
21
- run: cargo install cargo-fuzz --locked
32
+ run: cargo install cargo-fuzz@0.13.2 --locked
22
33
 
23
- - uses: Swatinem/rust-cache@v2
34
+ - uses: Swatinem/rust-cache@a45951ff880207c249adf57334cf2e9bd81d6e1e # v2
24
35
  with:
25
36
  workspaces: fuzz
26
37