Skip to content

QA: run_qa v1.6 form + ExplicitImports (root + sublibs)#1237

Draft
ChrisRackauckas-Claude wants to merge 4 commits into
SciML:masterfrom
ChrisRackauckas-Claude:qa-run_qa-v16-explicit-imports
Draft

QA: run_qa v1.6 form + ExplicitImports (root + sublibs)#1237
ChrisRackauckas-Claude wants to merge 4 commits into
SciML:masterfrom
ChrisRackauckas-Claude:qa-run_qa-v16-explicit-imports

Conversation

@ChrisRackauckas-Claude

Copy link
Copy Markdown
Contributor

Ignore until reviewed by @ChrisRackauckas. Draft.

Converts this monorepo's QA — the root test/qa and every lib/<Sub>/test/qa (27 sublibraries) — to SciMLTesting 1.6's run_qa form and turns on the six ExplicitImports checks fleet-wide.

Per QA env

  • qa.jlusing SciMLTesting, <Module>, JET + using Test + one run_qa(<Module>; explicit_imports = true, …) call. The module under test for a sublibrary is that sublibrary's module.
  • test/qa/Project.tomlSciMLTesting = "1.6" (added as dep + compat); Aqua and JET kept (both run); ExplicitImports comes transitively from SciMLTesting (not listed). [sources] develop wiring preserved exactly.

ExplicitImports (goal: 0 hard FAIL)

  • no_implicit_imports: every module is a facade that @reexports SciMLBase/OptimizationBase (+ usings helper modules); the implicit-import surface is module names that can't be made explicit without restructuring → ei_broken = (:no_implicit_imports,) fleet-wide.
  • all_qualified_accesses_are_public / all_explicit_imports_are_public / all_qualified_accesses_via_owners: per-env ei_kwargs ignore-lists of the specific names owned by SciMLBase / OptimizationBase / the backend / Base that are not (yet) declared public. (Closing those out upstream is the standard public-declaration follow-up.)
  • no_stale_explicit_imports: stale names kept + ignored (intentionally re-surfaced API; e.g. Optimization.instantiate_function is reached as a qualified name by the test suite).
  • OptimizationPyCMA / OptimizationSciPy load a CondaPkg-backed Python env at precompile (no network in the harness), so their EI checks are conservatively ei_broken (the failing set verified statically from their source).

Pre-existing Aqua reds cleared

The sublibrary QA lanes added in #1223 have been red on master for reasons independent of the harness form (they fail identically under the old Aqua.test_all). This PR fixes them so the converted lanes are green-or-broken:

  • deps_compat: add the missing [compat] entries for [extras]/[deps]/[weakdeps] across the sublibraries (stdlibs → "1"; others to a permissive floor consistent with existing repo compat).
  • stale_deps: drop the unused PDMats from OptimizationBase [deps]; move the test-only Manifolds from [deps] to [extras] + the test target in OptimizationManopt.
  • piracies: each solver wrapper deliberately extends SciMLBase's trait + __init/__solve interface onto its backend optimizer types → declare those foreign types via aqua_kwargs = (; piracies = (; treat_as_own = […])) (root, MOI, Base, Evolutionary, Metaheuristics, MultistartOptimization, NLPModels, NLopt, OptimJL, Optimisers).
  • undefined_exports: OptimizationMadNLP/OptimizationManopt (solve!), OptimizationMetaheuristics (summary) and OptimizationNOMAD (solve) @reexport two packages that both export the same name, leaving it an unresolved conflict binding → tracked as aqua_broken = (:undefined_exports,) (records Broken, auto-flags if a maintainer later resolves which binding wins).

Verification

Run locally against released SciMLTesting 1.6.0 on Julia 1.10 (QA lanes run on lts + 1, never pre, so JET-on-prerelease is not a concern here). Green-or-broken with 0 FAIL for: root, OptimizationBase, OptimizationBBO, OptimizationMOI, OptimizationEvolutionary, OptimizationOptimisers, OptimizationOptimJL, OptimizationManopt, OptimizationMadNLP, OptimizationMetaheuristics, OptimizationNOMAD. The remaining Aqua sub-checks (ambiguities / unbound_args / project_extras / persistent_tasks) verified clean across all 24 loadable sublibraries. CI covers the rest.

Sublibraries converted: 27 (+ root).

🤖 Generated with Claude Code

ChrisRackauckas and others added 4 commits June 25, 2026 14:10
Convert the root test/qa and every lib/<Sub>/test/qa to SciMLTesting 1.6's
`run_qa(<Module>; explicit_imports = true, ...)` form and enable the six
ExplicitImports checks across the whole monorepo.

Per QA env:
  * qa.jl -> `using SciMLTesting, <Module>, JET; using Test` + a single run_qa call.
  * test/qa/Project.toml -> SciMLTesting compat "1.6" (+ dep); Aqua and JET kept
    (both run); ExplicitImports comes transitively from SciMLTesting. [sources]
    wiring preserved.

ExplicitImports: 0 hard FAIL everywhere. no_implicit_imports is the facade
`@reexport`/`using` module-name reliance and is marked ei_broken fleet-wide; the
public-API and via-owners findings are per-env `ignore`-lists of names owned by
SciMLBase/OptimizationBase/the backend/Base that are not (yet) declared public;
stale explicit imports are kept+ignored (re-surfaced API / reached as Mod.name).
PyCMA and SciPy load CodaPkg-backed Python at precompile, so their EI checks are
conservatively ei_broken (verified statically from their source).

Also clears the pre-existing Aqua reds that left the new sublibrary QA lanes red
since SciML#1223 (these fail identically under the old `Aqua.test_all` form):
  * deps_compat: add the missing [compat] entries for [extras]/[deps]/[weakdeps]
    across the sublibraries (stdlibs -> "1"; others to a permissive floor).
  * stale_deps: drop the unused `PDMats` dep from OptimizationBase; move the
    test-only `Manifolds` from [deps] to [extras]+test target in OptimizationManopt.
  * piracies: each solver-wrapper intentionally extends SciMLBase's
    trait/__init/__solve interface onto its backend optimizer types -> declare
    those foreign types via `aqua_kwargs = (; piracies = (; treat_as_own = [...]))`.
  * undefined_exports: MadNLP/Manopt (`solve!`), Metaheuristics (`summary`) and
    NOMAD (`solve`) `@reexport` two packages exporting the same name, leaving it an
    unresolved conflict binding -> tracked as `aqua_broken = (:undefined_exports,)`.

Verified against released SciMLTesting 1.6.0 on Julia 1.10 (QA lanes run lts+1,
never pre): root, OptimizationBase, OptimizationBBO, OptimizationMOI,
OptimizationEvolutionary, OptimizationOptimisers, OptimizationOptimJL,
OptimizationManopt, OptimizationMadNLP, OptimizationMetaheuristics and
OptimizationNOMAD all green-or-broken with 0 FAIL; the remaining Aqua sub-checks
(ambiguities/unbound_args/project_extras/persistent_tasks) verified clean across
all 24 loadable sublibraries. CI covers the rest.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…eased base libs

SciMLTesting 1.7.0 now runs check_all_qualified_accesses_are_public and
check_all_explicit_imports_are_public only on Julia >= 1.11 (skipped on the LTS),
and the base-lib make-public round shipped (SciMLBase 3.24.0, OptimizationBase 5.1.3,
CommonSolve 0.2.9, Symbolics 7.28.1, SymbolicUtils 4.36.0, ModelingToolkit 11.29.0,
ArrayInterface 7.26.0). Many per-repo public-API ignore entries are therefore now
redundant.

Emptied both public-API ignore-lists in every qa env, then re-derived the minimal
surviving set by running each QA group on Julia 1.12 against the registered releases
(Pkg-resolved, no dev) and restoring only the names the checks still flag as
non-public. The flagged names are owned by SciMLBase / OptimizationBase / Base /
SciMLStructures / SymbolicUtils / the backend package and remain non-public on the
released versions (imported/accessed from a module that has not declared them public);
the proper fix is upstream `public` declarations, tracked against SciML/Optimization.jl.
Removed entries are names the make-public round turned public (e.g. Success, Failure,
MaxIters, MaxTime, build_solution, has_init, NullParameters, setup, update, ...).

Verified on Julia 1.12 (public checks run): each QA group's two public checks pass with
the trimmed lists. Verified on Julia 1.10 LTS (public checks skipped per SciMLTesting
1.7): root + OptimizationBase + OptimizationOptimisers + OptimizationNLPModels QA groups
green-or-broken (15 pass / 1 broken / 0 fail). OptimizationPyCMA and OptimizationSciPy
keep all_qualified_accesses_are_public in ei_broken (CondaPkg-gated envs, not analyzable
without conda). no_implicit_imports / no_stale_explicit_imports / *_via_owners ignores
and aqua/jet markers are untouched.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…eleases (SciMLBase 3.27.0)

The prior trim was derived against SciMLBase 3.24.0 / OptimizationBase 5.1.3. The
full make-public round is now registered (SciMLBase 3.27.0), which turned several
more accessed/imported names public — most consistently the solver-trait predicates
`allowsbounds` and `allowsconstraints`, plus `build_solution` and the abstract
algorithm type `AbstractDAEAlgorithm`. Those entries are now redundant in the
per-repo public-API ignore-lists.

Re-derived the minimal surviving set for every analyzable qa env by running
ExplicitImports' check_all_qualified_accesses_are_public /
check_all_explicit_imports_are_public with an empty ignore on Julia 1.12 against the
Pkg-resolved registered releases (no dev), and set each ignore-list to exactly the
names the checks still flag. OptimizationQuadDIRECT was resolved with its git-only
`QuadDIRECT` dependency added so it could be analyzed like CI does.

Removed (now public on the resolved SciMLBase 3.27.0): `allowsbounds`,
`allowsconstraints` (Auglag/BBO/CMAEvolutionStrategy/Evolutionary/GCMAES/Ipopt/
LBFGSB/MadNLP/Metaheuristics/MOI/MultistartOptimization/NLopt/NOMAD/ODE/OptimJL/
PRIMA/QuadDIRECT/SpeedMapping as applicable), `build_solution` (Optimisers),
`AbstractDAEAlgorithm` (ODE). OptimizationBase drops `allowsbounds`/`allowsconstraints`
from all_explicit_imports_are_public.

Survivors kept are genuinely still non-public on the resolved releases and are owned
by SciMLBase (`__init`/`__solve`/`allowscallback`/`requires*`/`MaxSense`/`MinSense`/
`ObjSense`/`NoAD`/`Abstract*`/...), OptimizationBase (`OptimizationStats`/`OptimizationState`/
`_check_and_convert_*`/`ReInitCache`/`instantiate_function`/`supports_sense`/...), Base
(`@logmsg`/`LogLevel`/`structdiff`), ForwardDiff (`gradient`), or each backend
(BlackBoxOptim/CMAEvolutionStrategy/Evolutionary/Ipopt/MadNLP/Manopt/Metaheuristics/
MathOptInterface/QuadDIRECT/...). The proper fix for the SciMLBase/OptimizationBase
survivors is upstream `public` declarations, tracked against SciML/Optimization.jl.

OptimizationManopt is unchanged: its dependency tree resolves SciMLBase 2.155.1, where
`build_solution`/`allowsbounds` remain non-public, so its list is already minimal there.

Verified on Julia 1.12 (public checks run): root + OptimizationBase +
OptimizationOptimisers + OptimizationMOI QA groups each pass both public-API EI checks
with the trimmed lists (ExplicitImports testset 5 pass / 1 broken / 0 fail — the broken
one is the intentional no_implicit_imports). The remaining `JET-test failed` in the
OptimizationBase/Optimisers/MOI QA groups is a pre-existing OptimizationBase 5.1.3 source
finding (undefined local `lagrangian`/`cons_oop` in OptimizationDISparseExt.jl) and is
independent of this EI-only change. no_implicit_imports / no_stale_explicit_imports /
*_via_owners ignores and aqua/jet markers are untouched. OptimizationPyCMA and
OptimizationSciPy keep their public checks in ei_broken (CondaPkg-gated, not analyzable
without conda).

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The run_qa v1.6 conversion newly runs JET typo-mode and the public-API
ExplicitImports checks, surfacing issues the old hand-rolled qa.jl never
exercised. Resolve each per its nature:

Real fixes (verified JET-clean):
* OptimizationGCMAES: hoist the gradient closure `g` out of the
  `!isnothing(cache.f.grad)` guard. `g` was defined only inside the guard
  but referenced in the `isnothing(...) ? _loss : (_loss, g)` ternary, which
  JET flagged as `g may be undefined`. The closure body never calls
  `cache.f.grad` at construction, so defining it unconditionally is behavior-
  preserving.
* OptimizationSciPy: `safe_get_message` called `pytypeof`, which does not
  exist in PythonCall (the function is `pytype`). This is a genuine latent
  UndefVarError on the non-str/non-list message fallback path; JET caught it.

EI ignore-list gap:
* SimpleOptimization: add the still-non-public `OptimizationStats`, `__solve`,
  and `_check_and_convert_maxiters` to `all_qualified_accesses_are_public`.

Documented jet_broken=true (pre-existing latent issues the conversion merely
surfaces; src unchanged from master, fixes belong in separate solver PRs):
* OptimizationLBFGSB (`res`), OptimizationOptimisers (`x`),
  OptimizationSophia (`x`), OptimizationMetaheuristics (`opt_bounds`):
  loss/result variables assigned only inside a loop/guard and read after.
* OptimizationNOMAD (`bb`/`bbcons`): closures defined in correlated if/else
  arms JET cannot prove correlated.
* OptimizationNLopt (`thetacache`/`Jthetacache`): closure-captured-and-
  reassigned bindings boxed by Julia; benign closure-capture artifact.

Verified locally on Julia 1.12.6 (QA lane = julia-1): each affected sublib's
QA group passes with 0 fail / 0 error (broken markers as documented).

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
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