[AI] Curate the public API instead of blanket-reexporting dependencies - #1286
Conversation
Every package in the monorepo `@reexport`ed its dependencies wholesale, so
`using Optimization` put 263 names in scope and `using OptimizationOptimJL` put
298 — none of which either package owned. 34 came from SciMLOperators
(`AddVector`, `BlockDiagonalOperator`, `update_coefficients!`), and the surface
included `DynamicalSDEFunction`, `DDEProblem` and `EigenvalueProblem`. Of the
263, the entire repo referenced 65.
OptimizationBase now `using`s SciMLBase/ADTypes/SciMLLogging and states its
public API in explicit `export` lists: its own types plus the problem/solution
API and the nine `Auto*` types a user needs. Optimization re-exports that
curated set and nothing else. The solver packages stop passing OptimizationBase
through and expose only their own solvers, so `using OptimizationOptimJL` now
means `LBFGS`, `BFGS`, `IPNewton` and friends. Users load `Optimization`
alongside the solver package, which is what the docs already showed everywhere
but one page.
Optimization 263 public, 0 owned -> 39
OptimizationBase 262 public, 6 owned -> 38
OptimizationOptimJL 298 public, 0 owned -> 36
Dropping the reexports exposed five defects they had been masking:
- OptimizationMOI and OptimizationIpopt use `ADTypes.AutoSymbolics` and
`ADTypes.AutoSparse` qualified without declaring ADTypes at all; they
compiled only because the reexport chain happened to bind the name.
- OptimizationCMAEvolutionStrategy imported the SciMLBase *module* from
OptimizationBase, and OptimizationLBFGSB took `ReturnCode` from there rather
than from SciMLBase, which owns it.
- OptimizationPyCMA marked `all_qualified_accesses_via_owners` as broken; it
passes once accesses go to their owners, so the marker is removed.
17 packages used `@SciMLMessage` without depending on SciMLLogging and now
declare it. `run_qa`'s reexport audit is satisfied without disabling it: the
nine glue packages allow exactly their backend module, the two umbrella
packages list their curated re-surface, and the remaining 18 need no
allow-list because they expose nothing they do not own.
Breaking: Optimization and OptimizationBase 5 -> 6, sublibraries by their
SemVer rule, with intra-monorepo compat bounds updated to match.
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014Uj4Pu1LKHYqLSTLfPYDPo
SebastianM-C
left a comment
There was a problem hiding this comment.
What should be the use cases when one uses Optimization vs OptimizationBase?
|
|
||
| ```@example PyCMA | ||
| using OptimizationPyCMA | ||
| using Optimization, OptimizationPyCMA |
There was a problem hiding this comment.
Should users have this or OptimizationBase?
There was a problem hiding this comment.
I guess OptimizationBase
There was a problem hiding this comment.
Done in a37c8f4 — the example is now using OptimizationBase, OptimizationPyCMA.
Verified locally on Julia 1.11 (fresh env, both packages deved from this branch): the block runs to ReturnCode.Success with sol.u = [0.8, 0.64], sol.objective = 0.04.
For the record, my PR description was wrong to call Optimization "the documented pattern on every doc page but one" — getting_started.md, lbfgsb.md, prima.md, sophia.md and the first ipopt.md example already use OptimizationBase. The docs are split roughly 30 Optimization / 6 OptimizationBase, with the front door (getting_started.md) on OptimizationBase. Harmonizing the remaining pages is a separate PR if you want it — say the word.
Matches getting_started.md and the LBFGSB/PRIMA/Sophia pages. Addresses review feedback on the pycma.md hunk. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A9dFnCQK2GVSNTCJP6ZMG2
The docs were split between `using Optimization` and `using OptimizationBase`, with getting_started.md, lbfgsb.md, prima.md and sophia.md already on the latter. Settle on OptimizationBase everywhere, per review feedback on the pycma.md hunk. names(Optimization) is names(OptimizationBase) plus the symbol :Optimization, and solve/init/solve!/reinit!/AutoForwardDiff/OptimizationProblem resolve to identical bindings in both, so this is behaviour-preserving. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A9dFnCQK2GVSNTCJP6ZMG2
`@reexport using SciMLBase` exported names(SciMLBase), which always contains
the symbol SciMLBase itself, so the module binding landed in every namespace
that did `using Optimization`. Curating the exports removes it, and the docs
were depending on it in two places:
- 21 `SciMLBase.OptimizationProblem`/`OptimizationFunction` calls, 18 of them
in executed @example blocks, which would throw UndefVarError and fail the
build (@example errors are not covered by the existing warnonly list).
OptimizationBase exports both names, so drop the qualification.
- 5 @docs entries under API/ naming SciMLBase types. No page sets
CurrentModule, so Documenter resolves them in Main; make.jl now binds
SciMLBase explicitly.
rosenbrock.md, linearandinteger.md and ode.md `using SciMLBase` for real and
are left as they are.
Verified on Julia 1.11: master binds SciMLBase and ADTypes for all four
entry-package x solver combinations tested, this branch binds neither.
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A9dFnCQK2GVSNTCJP6ZMG2
|
Followed up on the pycma thread by harmonizing the rest of the docs, and that turned up a build-breaking regression in this PR. 1. Docs entry package (2ac8c22)The docs were split, not uniform — my PR description was wrong to say Behaviour-preserving, verified on Julia 1.11: and 2. This PR breaks the docs build (6788bd3)
Two things depended on it:
This slipped through because the test plan covers Doc blocks re-run verbatim after the fix, on Julia 1.11: Still open
|
Version conflicts in all 24 Project.toml files: master's SciML#1287/SciML#1290 synced versions to the General registry with patch bumps, this branch makes breaking bumps. A major bump subsumes a patch bump, so the branch versions are already the correct next breaking release off master's (e.g. BBO 0.4.10 -> 0.5.0, root 5.6.6 -> 6.0.0); no versions are skipped. Verified master touched only the `version =` line in each conflicted file. Master's new second_order_warning_test.jl does `SciMLBase.requireshessian(...)`, which only resolved through the reexport this branch removes. It now says `using SciMLBase` explicitly; SciMLBase is already a dep of OptimizationBase. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A9dFnCQK2GVSNTCJP6ZMG2
Every example now loads OptimizationBase, so README and the index install instructions pointed at a package the docs never use. Both now lead with OptimizationBase, and index.md gains a short section on the relationship. `Optimization` re-exports OptimizationBase and adds nothing else — it pulls in Logging/ConsoleProgressMonitor/TerminalLoggers/LoggingExtras but never references them — so the new text says the two are interchangeable rather than inventing a distinction between them. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A9dFnCQK2GVSNTCJP6ZMG2
Removing every `@reexport` from OptimizationBase left Reexport in [deps] and [compat] with no user, which fails Aqua's stale-dependency check. The reexport check itself already passed; this is the leftover. QA on OptimizationBase: 19 pass / 1 fail / 1 broken before, 20 pass / 1 broken after. The remaining broken is `ei_broken = (:no_implicit_imports,)`, which is already on master. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A9dFnCQK2GVSNTCJP6ZMG2
`using SciMLBase: OptimizationStats, OptimizationFunction` predates this branch, but on master `@reexport using OptimizationBase` re-exported every name in names(OptimizationBase), OptimizationFunction among them — and exporting a name counts as using it, so the import was not stale. Removing the reexport orphans it, and ExplicitImports' no_stale_explicit_imports errors. The name is used nowhere else in the package. QA on OptimizationLBFGSB, Julia 1.11: master: 18 pass, 2 fail (JET + reexports), 1 broken before: 19 pass, 1 fail (JET), 1 error (stale import), 1 broken after: 19 pass, 1 fail (JET), 1 broken The remaining JET failure is byte-identical to master's (same 9 toplevel errors, from the LBFGSB struct colliding with the LBFGSB package binding) and is already tracked as a follow-up. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A9dFnCQK2GVSNTCJP6ZMG2
|
Rebase + follow-up changes pushed. The branch is MERGEABLE again (was CONFLICTING). Merge (f6be113)Done as a merge rather than a rebase: this branch already contains a merge commit and has review comments anchored to it, so a rebase would mean force-pushing over a branch under review. Say the word if you want the literal rebase. All 24
Three more things this branch brokeRunning the suite rather than trusting the test plan turned up three defects, all the same root cause — deleting the reexports orphaned things that were only alive through them. 1. Master's new 2. 3.
The one remaining fail is JET, byte-identical to master's (same 9 toplevel errors, from the QA sweep, all 28 packages23/28 pass. Of the 5 failures, 4 ( Docs
Not done17 packages still Verified locally on Julia 1.11: |
Independent of #1283 and #1284 — branched from
master.Why
run_qa's reexport audit has failed onmastersince SciMLTesting#28 enabledcheck_reexportsby default (2026-07-21, SciMLTesting 2.4.0). The obvious fix isreexports_allow, but the check was pointing at something real, so this curates the API instead.Every package
@reexported its dependencies wholesale:OptimizationOptimizationBaseOptimizationOptimJLusing OptimizationOptimJLbrought in 298 names, not one of them its own: 155 from SciMLBase, 38 ADTypes, 34 from SciMLOperators (AddVector,BlockDiagonalOperator,update_coefficients!), 30 Optim, 16 SciMLLogging, 4 NLSolversBase, 4 CommonSolve. The surface includedDynamicalSDEFunction,DDEProblem,EigenvalueProblem. Of the 263 namesOptimizationexported, the entire monorepo referenced 65.What changed
OptimizationBase—@reexport using SciMLBase, ADTypes, SciMLLoggingbecomes plainusingplus explicitexportlists: its own types, the problem/solution API (OptimizationProblem,OptimizationFunction,solve,init,solve!,remake,ReturnCode, senses, stats), and the nineAuto*types the repo actually uses.Optimization— re-exports that curated set and nothing else.OptimizationBasethrough. Every surviving@reexportsurfaces the package's own backend solvers, which is the glue package's job. Also caughtOptimizationODEreexporting all of SciMLBase andOptimizationNLPModelsall of ADTypes.Users write
using Optimization, OptimizationOptimJL, already the documented pattern on every doc page but one (pycma.md, updated).Five defects the reexports were masking
OptimizationMOIusesADTypes.AutoSymbolics/AutoSparseinnlp.jland never declared ADTypes.OptimizationIpopt— same, inevaluator.jl. Both compiled only because the reexport chain bound the name.OptimizationCMAEvolutionStrategyimported the SciMLBase module fromOptimizationBase(using OptimizationBase: SciMLBase), which ExplicitImports flags as bothExplicitImportsFromNonOwnerExceptionandNonPublicExplicitImportsException.OptimizationLBFGSBtookReturnCodefromOptimizationBaserather than SciMLBase, which owns it.OptimizationPyCMAhadall_qualified_accesses_via_ownersmarked@test_broken; it passes once accesses go to owners, so the stale marker is removed.Separately, 17 packages used
@SciMLMessagewithout depending on SciMLLogging and now declare it.QA stays enabled, not allow-listed away
Nine glue packages allow exactly their backend module; the two umbrella packages list their curated re-surface explicitly; the remaining 18 need no allow-list at all. Adding a reexport is now a deliberate edit to a short list.
Versions
Breaking.
Optimization5.6.5→6.0.0,OptimizationBase5.2.2→6.0.0, each sublibrary by its SemVer rule (0.x→0.(x+1),1.x→2.0.0), with intra-monorepo compat bounds updated across all package, test and docs environments.Test plan
Run locally on Julia 1.11, full sweep after the final change:
Core— 28/28 pass (root + all 27 sublibraries)QA— 27/28 passOptimizationLBFGSB, is pre-existing: on a cleanmastercheckout it fails 2 checks (JET and reexport); on this branch it fails only the JET one. Verified by stashing this branch and re-running.[deps]/[extras]/[weakdeps]entry re-validated as a UUIDFollow-ups, deliberately not in this PR
MaxSense/MinSense/ObjSense/OptimizationStatsare core user-facing API that SciMLBase does not declarepublic. They are still re-exported here so nothing breaks, but the clean fix is a SciMLBase PR declaring and documenting them.OptimizationLBFGSB's JET failure onmaster.🤖 Generated with Claude Code
https://claude.ai/code/session_014Uj4Pu1LKHYqLSTLfPYDPo