From ed1d10e7d4f621fb7c3b681d6e6af55cd53a3e98 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Thu, 25 Jun 2026 06:11:40 -0400 Subject: [PATCH 1/4] QA: run_qa v1.6 form + ExplicitImports Convert the hand-rolled test/qa/qa.jl (manual Aqua + ExplicitImports + JET) onto the SciMLTesting 1.6 run_qa form with ExplicitImports enabled (explicit_imports = true), running all six ExplicitImports checks. ExplicitImports findings: - no_stale_explicit_imports: removed the genuinely-unused SciMLLogging imports DebugLevel and ErrorLevel from src/Integrals.jl. The remaining stale-reported names (None/Minimal/Standard/Detailed/All/MessageLevel/AbstractVerbositySpecifier) are referenced only inside the @verbosity_specifier macro expansion (the macro generates IntegralVerbosity(::None)/(::Minimal)/... preset constructors and MessageLevel/AbstractVerbositySpecifier type guards in Integrals' scope), which ExplicitImports cannot see through; dropping them breaks precompile (UndefVarError: `None` not defined), so they are kept and ignored. - all_qualified_accesses_are_public: ignore six non-public names accessed qualified from other packages (AbstractIntegralAlgorithm/Success/build_solution from SciMLBase, fast_scalar_indexing from ArrayInterface, get_extension from Base, seed! from Random). - The other four EI checks pass clean. Preserve the piracies treat_as_own = [IntegralProblem, SampledIntegralProblem] tweak via aqua_kwargs. The bespoke @report_opt opt-mode solver-path type-stability guards (incl. the VEGAS <= 2 regression bound) are kept as a separate testset, orthogonal to run_qa's package-level JET typo check. test/qa/Project.toml: drop ExplicitImports (transitive via SciMLTesting), bump SciMLTesting compat to "1.6". Keep Aqua (test_ambiguities child process needs it a direct dep), JET, and SafeTestsets (the run_tests folder harness wraps each group file in @safetestset, which needs SafeTestsets in the active sub-env). Verified locally on Julia 1.10 against released SciMLTesting 1.6.0: QA group 24/24 pass, 0 fail/error/broken (Quality Assurance 18/18 + JET opt-mode 6/6). Co-Authored-By: Chris Rackauckas Co-Authored-By: Claude Opus 4.8 (1M context) --- src/Integrals.jl | 4 +-- test/qa/Project.toml | 4 +-- test/qa/qa.jl | 73 ++++++++++++++++++++++++-------------------- 3 files changed, 43 insertions(+), 38 deletions(-) diff --git a/src/Integrals.jl b/src/Integrals.jl index 9273c43b..18a4fea1 100644 --- a/src/Integrals.jl +++ b/src/Integrals.jl @@ -11,8 +11,8 @@ using SciMLBase: init, solve! using LinearAlgebra: LinearAlgebra, /, norm using Random: Random using ArrayInterface: ArrayInterface -using SciMLLogging: SciMLLogging, @SciMLMessage, MessageLevel, Silent, DebugLevel, - InfoLevel, WarnLevel, ErrorLevel, @verbosity_specifier, AbstractVerbositySpecifier, +using SciMLLogging: SciMLLogging, @SciMLMessage, MessageLevel, Silent, + InfoLevel, WarnLevel, @verbosity_specifier, AbstractVerbositySpecifier, None, Minimal, Standard, Detailed, All include("verbosity.jl") diff --git a/test/qa/Project.toml b/test/qa/Project.toml index 42e6aea2..caefd745 100644 --- a/test/qa/Project.toml +++ b/test/qa/Project.toml @@ -1,6 +1,5 @@ [deps] Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" -ExplicitImports = "7d51a73a-1435-4ff3-83d9-f097790105c7" Integrals = "de52edbc-65ea-441a-8357-d3a637375a31" JET = "c3a54625-cd67-489e-a8e7-0a5a0ff4e31b" SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f" @@ -12,10 +11,9 @@ Integrals = {path = "../.."} [compat] Aqua = "0.8" -ExplicitImports = "1.14.0" Integrals = "5" JET = "0.9, 0.10, 0.11.3" SafeTestsets = "0.1, 1" -SciMLTesting = "1" +SciMLTesting = "1.6" Test = "1.10" julia = "1.10" diff --git a/test/qa/qa.jl b/test/qa/qa.jl index 24badda3..29ca57e3 100644 --- a/test/qa/qa.jl +++ b/test/qa/qa.jl @@ -1,37 +1,45 @@ -using Integrals -using Aqua -using ExplicitImports +using SciMLTesting, Integrals, Test using JET -using Test -using LinearAlgebra: norm -@testset "Aqua" begin - Aqua.find_persistent_tasks_deps(Integrals) - Aqua.test_ambiguities(Integrals, recursive = false) - Aqua.test_deps_compat(Integrals) - Aqua.test_piracies( - Integrals, - treat_as_own = [IntegralProblem, SampledIntegralProblem] - ) - Aqua.test_project_extras(Integrals) - Aqua.test_stale_deps(Integrals) - Aqua.test_unbound_args(Integrals) - Aqua.test_undefined_exports(Integrals) -end - -@testset "ExplicitImports" begin - @test check_no_implicit_imports(Integrals) === nothing - # Note: norm is used in default parameters in included files (algorithms.jl) - # which ExplicitImports may not detect properly, so we ignore it - @test check_no_stale_explicit_imports( - Integrals; ignore = ( - :norm, :AbstractVerbositySpecifier, :MessageLevel, - :DebugLevel, :Detailed, :ErrorLevel, :Minimal, :None, :Standard, :All, - ) - ) === nothing -end +run_qa( + Integrals; + explicit_imports = true, + aqua_kwargs = (; + # IntegralProblem / SampledIntegralProblem are SciMLBase types this package + # owns the integral-solver methods for, so dispatching on them is not piracy. + piracies = (; treat_as_own = [IntegralProblem, SampledIntegralProblem]), + ), + ei_kwargs = (; + no_stale_explicit_imports = (; + # Referenced only inside `@verbosity_specifier IntegralVerbosity` (src/verbosity.jl): + # the macro generates `IntegralVerbosity(::None)` / `(::Minimal)` / ... preset + # constructors and `MessageLevel` / `AbstractVerbositySpecifier` type guards that + # need these bare names in `Integrals`'s scope. ExplicitImports cannot see through + # the macro, so it reports them stale; dropping the imports breaks precompile + # (UndefVarError: `None` not defined). + ignore = ( + :AbstractVerbositySpecifier, :MessageLevel, + :None, :Minimal, :Standard, :Detailed, :All, + ), + ), + all_qualified_accesses_are_public = (; + # Non-public names accessed qualified from other packages (stable cross-package + # APIs Integrals relies on; may become public as those libs release): + # AbstractIntegralAlgorithm, Success, build_solution -> SciMLBase + # fast_scalar_indexing -> ArrayInterface + # get_extension -> Base + # seed! -> Random + ignore = ( + :AbstractIntegralAlgorithm, :Success, :build_solution, + :fast_scalar_indexing, :get_extension, :seed!, + ), + ), + ), +) -@testset "JET static analysis" begin +# Type-stability (JET opt-mode) regression guards for the hot solver paths. These are +# repo-specific @report_opt checks, orthogonal to run_qa's package-level JET typo check. +@testset "JET opt-mode solver paths" begin @testset "QuadGKJL" begin f = (x, p) -> x^2 prob = IntegralProblem(f, (0.0, 1.0)) @@ -73,11 +81,10 @@ end # VEGAS has some inherent type instability issues due to: # 1. Captured variables in closures (necessary for in-place operations) # 2. Runtime dispatch for integrand type checking - # We verify the number of issues is bounded and doesn't regress + # We verify the number of issues is bounded and doesn't regress. f = (x, p) -> x^2 prob = IntegralProblem(f, (0.0, 1.0)) rep = @report_opt target_modules = (Integrals,) solve(prob, VEGAS()) - # Allow up to 2 reports (captured variable + runtime dispatch for type check) @test length(JET.get_reports(rep)) <= 2 end end From 714a8b9fec557a2f1fa3e61e2d5a2070c1fe5a6d Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Thu, 25 Jun 2026 11:05:01 -0400 Subject: [PATCH 2/4] QA: import AbstractVerbosityPreset for @verbosity_specifier macro The `@verbosity_specifier IntegralVerbosity` macro (SciMLLogging) expands the keyword constructor `IntegralVerbosity(; preset, ...)` with an unqualified `preset isa AbstractVerbosityPreset` guard, so the bare name must resolve in `Integrals`'s scope. It was never imported, so `IntegralVerbosity(; preset=...)` threw `UndefVarError(:AbstractVerbosityPreset, Integrals)` at runtime; the v1.6 run_qa JET typo-mode check (report_package) surfaces this on Julia 1.12. Import `AbstractVerbosityPreset` from SciMLLogging and add it to the no_stale_explicit_imports ignore list (ExplicitImports cannot see the macro-generated reference). Co-Authored-By: Chris Rackauckas Co-Authored-By: Claude Opus 4.8 (1M context) --- src/Integrals.jl | 2 +- test/qa/qa.jl | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Integrals.jl b/src/Integrals.jl index 18a4fea1..107b0563 100644 --- a/src/Integrals.jl +++ b/src/Integrals.jl @@ -13,7 +13,7 @@ using Random: Random using ArrayInterface: ArrayInterface using SciMLLogging: SciMLLogging, @SciMLMessage, MessageLevel, Silent, InfoLevel, WarnLevel, @verbosity_specifier, AbstractVerbositySpecifier, - None, Minimal, Standard, Detailed, All + AbstractVerbosityPreset, None, Minimal, Standard, Detailed, All include("verbosity.jl") include("algorithms_meta.jl") diff --git a/test/qa/qa.jl b/test/qa/qa.jl index 29ca57e3..1dbdb69b 100644 --- a/test/qa/qa.jl +++ b/test/qa/qa.jl @@ -13,12 +13,13 @@ run_qa( no_stale_explicit_imports = (; # Referenced only inside `@verbosity_specifier IntegralVerbosity` (src/verbosity.jl): # the macro generates `IntegralVerbosity(::None)` / `(::Minimal)` / ... preset - # constructors and `MessageLevel` / `AbstractVerbositySpecifier` type guards that - # need these bare names in `Integrals`'s scope. ExplicitImports cannot see through - # the macro, so it reports them stale; dropping the imports breaks precompile - # (UndefVarError: `None` not defined). + # constructors and `MessageLevel` / `AbstractVerbositySpecifier` / + # `AbstractVerbosityPreset` type guards that need these bare names in `Integrals`'s + # scope. ExplicitImports cannot see through the macro, so it reports them stale; + # dropping the imports breaks the constructor at runtime + # (`IntegralVerbosity(; preset=Standard())` -> UndefVarError: `AbstractVerbosityPreset`). ignore = ( - :AbstractVerbositySpecifier, :MessageLevel, + :AbstractVerbositySpecifier, :AbstractVerbosityPreset, :MessageLevel, :None, :Minimal, :Standard, :Detailed, :All, ), ), From d5f3d05f12b1aef4cbcde728d3515823b5f381a2 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Fri, 26 Jun 2026 15:44:04 -0400 Subject: [PATCH 3/4] QA: drop now-redundant public-API explicit-imports ignores SciMLTesting 1.7 runs check_all_qualified_accesses_are_public and check_all_explicit_imports_are_public only on Julia >= 1.11, and the base libs have since published the names Integrals relies on: AbstractIntegralAlgorithm, build_solution -> SciMLBase 3.24.0 public Success -> no longer in SciMLBase fast_scalar_indexing -> ArrayInterface 7.26.0 public get_extension -> Base public seed! -> Random exported (public) With these released, the all_qualified_accesses_are_public ignore list is fully redundant, so it is removed. Verified on Julia 1.12 (checks run) both public-API checks are clean against the registered releases, and on Julia 1.10 (lts, checks skipped) the QA group is green. The remaining no_stale_explicit_imports ignore (macro-generated verbosity names) and aqua piracies kwargs are unchanged. Co-Authored-By: Chris Rackauckas Co-Authored-By: Claude Opus 4.8 (1M context) --- test/qa/qa.jl | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/test/qa/qa.jl b/test/qa/qa.jl index 1dbdb69b..a7aa633c 100644 --- a/test/qa/qa.jl +++ b/test/qa/qa.jl @@ -23,18 +23,6 @@ run_qa( :None, :Minimal, :Standard, :Detailed, :All, ), ), - all_qualified_accesses_are_public = (; - # Non-public names accessed qualified from other packages (stable cross-package - # APIs Integrals relies on; may become public as those libs release): - # AbstractIntegralAlgorithm, Success, build_solution -> SciMLBase - # fast_scalar_indexing -> ArrayInterface - # get_extension -> Base - # seed! -> Random - ignore = ( - :AbstractIntegralAlgorithm, :Success, :build_solution, - :fast_scalar_indexing, :get_extension, :seed!, - ), - ), ), ) From 2d4770d3d0f73bb9d8bb5b58d99d6adcbe8904e6 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Sat, 27 Jun 2026 00:18:53 -0400 Subject: [PATCH 4/4] QA: raise SciMLTesting floor to 1.7 for gated public-API checks The public-API ExplicitImports checks (all_qualified_accesses_are_public, all_explicit_imports_are_public) were dropped from their ignore lists in this PR. Those checks only behave correctly across Julia versions starting with SciMLTesting 1.7.0, which gates them to run on Julia >= 1.11 (where the `public` keyword and `Base.ispublic` exist) and skip on the 1.10 LTS (where a `public`-backported name is not recognized as public and the checks would spuriously flag genuinely-public names). Raising the QA-env floor from 1.6 to 1.7 guarantees a downgrade lane cannot pick a SciMLTesting that runs the public checks on 1.10 against the emptied ignore lists. Verified against the registered releases (SciMLBase 3.27.0, ArrayInterface 7.26.0, CommonSolve 0.2.9, SciMLTesting 1.7.0): - Julia 1.12 (public checks run): Quality Assurance 18/18 pass, no restorations needed for the emptied all_qualified_accesses_are_public list. - Julia 1.10 (public checks skip): Quality Assurance 16/16 pass. Co-Authored-By: Chris Rackauckas Co-Authored-By: Claude Opus 4.8 (1M context) --- test/qa/Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/qa/Project.toml b/test/qa/Project.toml index caefd745..c4db8a0d 100644 --- a/test/qa/Project.toml +++ b/test/qa/Project.toml @@ -14,6 +14,6 @@ Aqua = "0.8" Integrals = "5" JET = "0.9, 0.10, 0.11.3" SafeTestsets = "0.1, 1" -SciMLTesting = "1.6" +SciMLTesting = "1.7" Test = "1.10" julia = "1.10"