Skip to content

Raise Mooncake compat floor to 0.5.36 (fix Downgrade resolution)#65

Closed
ChrisRackauckas-Claude wants to merge 84 commits into
SciML:masterfrom
ChrisRackauckas-Claude:raise-mooncake-floor-0.5.36
Closed

Raise Mooncake compat floor to 0.5.36 (fix Downgrade resolution)#65
ChrisRackauckas-Claude wants to merge 84 commits into
SciML:masterfrom
ChrisRackauckas-Claude:raise-mooncake-floor-0.5.36

Conversation

@ChrisRackauckas-Claude

Copy link
Copy Markdown
Contributor

Raise the Mooncake [compat] floor to a single latest floor 0.5.36 in every Project.toml that declares Mooncake, dropping the old 0.5 union that let the downgrade min-resolution pin an ancient Mooncake. This is the "limit to latest Mooncake" fix for the promotion-caused Downgrade Unsatisfiable wall.

Raised floors

File Old New
Project.toml (root, [weakdeps] Mooncake) 0.5 0.5.36
test/Mooncake/Project.toml ([deps] Mooncake) 0.5 0.5.36

Root version bumped 1.9.3 -> 1.9.4 (a compat narrowing of a weakdep is a patch-level change, not a public-API change).

Verification (resolves_at_min = true)

Ran julia-actions/julia-downgrade-compat's downgrade.jl (Resolver.jl --min=@deps) on Julia 1.12.6 against the test/Mooncake env (the only env where Mooncake participates in a downgrade resolve):

[ Info: Running resolver on test/Mooncake with --min=@deps
[ Info: Successfully resolved minimal versions for test/Mooncake

Resolution succeeds: Mooncake pins to exactly 0.5.36, 33 packages resolved. So the floor-raise alone is sufficient here — the Resolver-capacity wall does not persist for this repo (resolves_at_min = true, #52 not required).

Note for context: this repo's Downgrade.yml only runs group: Core, where Mooncake is a [weakdeps] entry NOT in the root test target (test = ["Test", "SafeTestsets", "SciMLTesting"]), so in mode: deps Mooncake is absent from the merged root resolve entirely (verified). The Mooncake floor only affects the test/Mooncake group env, which resolves cleanly at =0.5.36.


Please ignore until reviewed by @ChrisRackauckas.

dependabot Bot and others added 30 commits November 24, 2025 18:44
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](actions/checkout@v4...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
This adds three new exported functions to help users debug wrapped functions:

- `unwrap(fww)`: Returns the original function that was wrapped, allowing
  users to debug it with tools like Debugger.jl or Infiltrator.jl
- `wrapped_signatures(fww)`: Returns a tuple of argument type signatures
- `wrapped_return_types(fww)`: Returns a tuple of return types

These functions address issue SciML#18 by providing a documented API for accessing
the wrapped function's source code and stepping through it with debuggers.

Closes SciML#18

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…ssue-18

Add introspection functions for debugging wrapped functions
Fixes formatting issues introduced in SciML#25.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…g-issue-25

Apply JuliaFormatter to introspection functions from SciML#25
Added a PrecompileTools workload to precompile common use patterns,
dramatically improving time-to-first-execution (TTFX):

- FunctionWrappersWrapper creation: ~0.088s -> ~0.0002s (518x faster)
- First call dispatch (Float64): ~0.58s -> ~0.00007s (8286x faster)
- Second type call dispatch (Int): ~0.053s -> ~0.00007s (757x faster)

The precompilation workload covers:
- Binary operations with Float64 and Int argument types
- Unary operations with Float64 and Int argument types
- Both creation and call dispatch for each

No invalidations were detected when loading the package.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…provements-20251230-001519

Add PrecompileTools to reduce TTFX by up to 8000x
…pendabot

Add Julia ecosystem to Dependabot configuration
…ons/checkout-6

Bump actions/checkout from 4 to 6
Updates the requirements on [Documenter](https://github.com/JuliaDocs/Documenter.jl) and [FunctionWrappersWrappers](https://github.com/chriselrod/FunctionWrappersWrappers.jl) to permit the latest version.

Updates `Documenter` to 1.16.1
- [Release notes](https://github.com/JuliaDocs/Documenter.jl/releases)
- [Changelog](https://github.com/JuliaDocs/Documenter.jl/blob/master/CHANGELOG.md)
- [Commits](JuliaDocs/Documenter.jl@v0.1.0...v1.16.1)

Updates `FunctionWrappersWrappers` to 0.1.3
- [Release notes](https://github.com/chriselrod/FunctionWrappersWrappers.jl/releases)
- [Commits](https://github.com/chriselrod/FunctionWrappersWrappers.jl/commits)

---
updated-dependencies:
- dependency-name: Documenter
  dependency-version: 1.16.1
  dependency-type: direct:production
  dependency-group: all-julia-packages
- dependency-name: FunctionWrappersWrappers
  dependency-version: 0.1.3
  dependency-type: direct:production
  dependency-group: all-julia-packages
...

Signed-off-by: dependabot[bot] <support@github.com>
…a-packages-be27efa2d9

Bump the all-julia-packages group across 1 directory with 2 updates
- Update CI workflow to use fredrikekre/runic-action@v1
- Remove .JuliaFormatter.toml configuration
- Format all source files with Runic.jl

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Switch from JuliaFormatter to Runic.jl for code formatting
…ements-20260108-030854

Add JET static analysis and type inference tests
Changed `rettypes` parameter type constraint from `Tuple{Vararg{DataType, K}}`
to `Tuple{Vararg{Type, K}}` to allow UnionAll types like `AbstractArray{Float64}`
or `JLArray{Float64}` as return types.

This is backwards compatible since `DataType <: Type`, so all existing code
continues to work. The underlying FunctionWrappers.jl already supports these
types.

Added tests for:
- BigFloat support (verifying arbitrary precision works)
- UnionAll return types (testing AbstractArray{Float64})

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…ck-20260107-150433

Allow UnionAll types in rettypes for improved interface compatibility
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](actions/checkout@v4...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
…ons/checkout-6

Bump actions/checkout from 4 to 6
Replaces the boolean `FB` type parameter with two orthogonal configuration axes:

Cache modes (how fallback FunctionWrappers are cached):
- NoCache: dynamic dispatch every call (1 alloc, legacy behavior)
- SingleCache: cache one FunctionWrapper for last arg types (0 alloc on hit)
- DictCache: cache per arg type in a Dict (0 alloc, multi-type)

Fallback policies (when fallback is allowed):
- Strict: always error on mismatch (legacy Val{false})
- AllowAll: always fall back (legacy Val{true})
- AllowNonIsBits: fall back only for non-isbits types, error for isbits mismatches

Default is SingleCache + AllowNonIsBits, which provides zero-allocation
fallback for BigFloat, SparseConnectivityTracer, and similar non-isbits types
while still catching isbits type mismatches as bugs.

The key mechanism is lazily creating and caching a FunctionWrapper for the
actual argument types on first fallback hit. Subsequent calls use the cached
wrapper's ccall path with no extra allocations.

Legacy API (Val{true}/Val{false} and FunctionWrappersWrapper{FW,Bool})
is preserved for backward compatibility, mapping to AllowAll/Strict + NoCache.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Breaking change: removes the boolean FB type parameter and Val{true}/Val{false}
API. The FunctionWrappersWrapper type now takes a fallback policy and cache
storage type as type parameters instead.

Cache modes (how fallback FunctionWrappers are cached):
- NoCache: dynamic dispatch every call (1 alloc per call)
- SingleCache: lazily cache a FunctionWrapper for last-seen arg types (0 alloc)
- DictCache: cache per arg type in a Dict (0 alloc, multi-type)

Fallback policies (when fallback is allowed):
- Strict: always error on type mismatch
- AllowAll: always fall back to original function
- AllowNonIsBits: fall back for non-isbits types, error for isbits mismatches

Default: SingleCache + AllowNonIsBits

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…lback-policy

Add configurable cache modes and fallback policies for non-isbits types
When FunctionWrappersWrapper is called in an AD context, these extensions
bypass the type-erased FunctionWrapper call and differentiate through the
original unwrapped function directly.

Enzyme extension: defines forward/reverse custom rules that unwrap the
function and use Enzyme.autodiff on the original function.

Mooncake extension: marks FunctionWrappersWrapper calls as primitive and
delegates to the FunctionWrapper's existing rrule from
MooncakeFunctionWrappersExt.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ChrisRackauckas and others added 28 commits April 23, 2026 08:21
…d-rule

Propagate set_runtime_activity through FWW Enzyme forward rules
`fredrikekre/runic-action@v1` (v1.4+) requires `julia` in PATH but no
longer installs it itself. Add `julia-actions/setup-julia@v2` before the
action so the format check actually runs (it has been silently passing
across many SciML repos for weeks).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
…ck-julia-setup

CI: install Julia in FormatCheck workflow so runic-action can run
Bumps [julia-actions/setup-julia](https://github.com/julia-actions/setup-julia) from 2 to 3.
- [Release notes](https://github.com/julia-actions/setup-julia/releases)
- [Commits](julia-actions/setup-julia@v2...v3)

---
updated-dependencies:
- dependency-name: julia-actions/setup-julia
  dependency-version: '3'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Relaxes the `func` argument type in the forward, augmented_primal, and
reverse rules from `Const{<:FunctionWrappersWrapper}` to
`Annotation{<:FunctionWrappersWrapper}` so that callers passing
`Duplicated{<:FunctionWrappersWrapper}` also dispatch through these rules
instead of falling off to a MethodError.

Closes SciML#48.

Why this is safe: a `FunctionWrappersWrapper` only carries
`FunctionWrapper`s plus cache storage; none of those fields have a
meaningful tangent.  The function shadow is therefore ignored — `func.val`
(the primal wrapper) is unwrapped and the inner `Enzyme.autodiff` call
delegates with `Const(f_orig)` exactly as in the previous `Const`-only
path.  Enzyme drives the rule with a `Duplicated` function annotation
when the outer `autodiff` call is differentiating through a closure that
captures an FWW — the SciML `NonlinearSolve` + `SciMLSensitivity` path
in the issue is one such case.

Adds four testsets that drive each forward / augmented_primal / reverse
rule with `Duplicated(fww, fww)` to lock in the broader dispatch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
The forward rules for batch width > 1 asserted
`shadow_result[1]::NTuple{W, T}` but `Enzyme.autodiff(Forward, …,
BatchDuplicated{T,W}, …)` returns the batch shadow wrapped in
`Enzyme.Compiler.AnonymousStruct` — a
`NamedTuple{(:1, :2, …), NTuple{W, T}}` (see
`Enzyme/src/compiler/utils.jl:480`).

The mismatch tripped the existing `Enzyme batch forward mode (width > 1)`
testset on `main` with:

```
TypeError: in typeassert, expected Tuple{Float64, Float64},
got a value of type @NamedTuple{1::Float64, 2::Float64}
```

Wrap the shadow in `Tuple(...)` before the type-assert so the rule's
return matches the `BatchDuplicated` shadow contract that Enzyme expects
from a forward rule.  Applies to both `{false, true, W>1, …}`
(shadow-only) and `{true, true, W>1, …}` (ForwardWithPrimal) rules.

The existing testset (which was failing on `main`) now passes.  Full
local test summary on Julia 1.11 + Enzyme v0.13.147:

```
FunctionWrappersWrappers.jl |   48     48
BigFloat support            |    5      5
UnionAll return types       |    2      2
Enzyme extension            |   44     44
Mooncake extension          |   13     13
```

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
…duplicated-fww

Accept Annotation{<:FunctionWrappersWrapper} in Enzyme rules (closes SciML#48)
…a-actions/setup-julia-3

Bump julia-actions/setup-julia from 2 to 3
Calls `EnzymeRules.forward` directly so the rule's actual return value
is observable.  The pre-existing `Enzyme.autodiff(Forward, …)`-driven
testset doesn't catch a regression on its own because the outer
`Enzyme.autodiff` ALSO wraps in `AnonymousStruct`, and `shadow[1]`
indexing works on both `NamedTuple` and `Tuple`.

The new testset asserts:
- the shadow-only rule (`{false, true, W=2, …}`) returns `NTuple{2, Float64}`,
  not `NamedTuple`;
- the ForwardWithPrimal rule (`{true, true, W=2, …}`) puts an
  `NTuple{2, Float64}` (not a `NamedTuple`) into `result.dval`;
- the conversion generalises to W = 3.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
…ward-typeassert

Fix batch-forward typeassert: Enzyme returns AnonymousStruct, not NTuple
`SingleCacheStorage` is a mutable struct and `DictCacheStorage` carries a
mutable `Dict`. Their fallback paths write a `FunctionWrapper` into the
storage on a cache miss. Without an `inactive_type` declaration Enzyme
conservatively treats any closure that captures a `FunctionWrappersWrapper`
as potentially writing to the storage, so `Enzyme.gradient`/`autodiff`
through such a closure can fail with `EnzymeMutabilityException` on the
captured argument.

The cache values are `FunctionWrapper`s — used purely for dispatch and
dynamic-call speedup. They never carry derivative data. Marking the three
storage types as `inactive_type` lets Enzyme prove the captured wrapper
readonly without affecting derivative correctness.

Defensive hardening prompted by the Enzyme-through-MTK-remake stack
documented in SciML/SciMLSensitivity.jl#1323, SciML/SciMLSensitivity.jl#1359,
and SciML/ModelingToolkit.jl#4550 — this PR alone is not sufficient to
unblock that path (the underlying NonlinearSolve + Enzyme interaction
still hits a separate `EnzymeMutabilityException` against the wrapped
function), but it removes one conservative-IPA layer for any user of FWW
under Enzyme.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
…tive-type

Declare cache-storage types as Enzyme inactive
Convert all CI to the SciML centralized reusable workflows (pinned @v1,
secrets: inherit on every caller).

- Tests: already a tests.yml@v1 caller (unchanged matrix; secrets already inherit).
  Moved the inline Documentation job out into its own workflow.
- Documentation: new documentation.yml@v1 caller (replaces inline docdeploy job).
- Runic (FormatCheck): convert inline fredrikekre/runic-action to runic.yml@v1.
- SpellCheck: new spellcheck.yml@v1 caller (was previously not present).
- Downgrade: new downgrade.yml@v1 caller (julia-version lts, skip Pkg,TOML, group Core).
- dependabot: remove the crate-ci/typos ignore (typos now runs via centralized caller).
- Apply Runic formatting to ext/ and test/ sources.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Centralize CI on SciML reusable workflows
…erge, docs-preview-cleanup) (SciML#55)

Adds the standard SciML centralized caller workflows that were missing:
- RunicSuggestions.yml (Runic auto-format suggestions on PRs)
- DependabotAutoMerge.yml (auto-merge Dependabot PRs)
- DocPreviewCleanup.yml (clean up doc previews on PR close)

Co-authored-by: ChrisRackauckas-Claude <noreply@anthropic.com>
Co-authored-by: Chris Rackauckas <accounts@chrisrackauckas.com>
Convert the root Tests.yml test job to the canonical thin caller of
SciML/.github grouped-tests.yml@v1, with the group x version matrix
declared once in test/test_groups.toml. The runtests.jl GROUP dispatch
(Core/nopre) already exists, so no test-runner change is needed.

The emitted root matrix reproduces the old hand-maintained matrix exactly
(5/5): Core on {lts,1,pre} and nopre on {lts,1}.

Co-authored-by: ChrisRackauckas-Claude <accounts@chrisrackauckas.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ciML#56)

- Replace inlined JuliaRegistries/TagBot with canonical SciML/.github tagbot.yml@v1 thin caller
- Remove stdlib-only skip: "Pkg,TOML" from Downgrade caller (centralized workflow auto-populates skip)

Co-authored-by: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Convert test/runtests.jl to SciMLTesting v1.2. This repo needs the
explicit-args form (not bare folder-discovery): the Enzyme/Mooncake test
groups run only under "All" yet are not declared in test_groups.toml, and the
BigFloat/UnionAll testsets must run under both Core and nopre. Folder-discovery
cannot express either, so runtests.jl uses run_tests with explicit core/groups
bodies and a curated all = ["Core", "Enzyme", "Mooncake"].

Layout:
- Core = test/basictests.jl + test/shared/bigfloat_unionall_tests.jl
- nopre = test/nopre/jet_tests.jl (sub-env) + the shared BigFloat/UnionAll file
- Enzyme = test/Enzyme/enzyme_tests.jl (main env)
- Mooncake = test/Mooncake/mooncake_tests.jl (main env)

Behavior-preserving for every CI-reachable GROUP (verified locally on Julia
1.11 via Pkg.test):
- Core  -> basictests (48) + BigFloat/UnionAll (7)
- nopre -> JET (7) + BigFloat/UnionAll (7)
- All   -> basictests (48) + BigFloat/UnionAll (7, once) + Enzyme (65) + Mooncake (13)

Deps: add SciMLTesting + SafeTestsets to the root test target and the nopre
sub-env; drop the now-unused Pkg test extra (the harness owns all Pkg ops).
Removed the stale committed test/nopre/Manifest.toml (regenerated at run time
by the harness's Pkg.develop + instantiate). test/test_groups.toml unchanged.

Co-authored-by: ChrisRackauckas-Claude <accounts@chrisrackauckas.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ciML#59)

* Raise FunctionWrappers compat floor to 1.1.3 to fix downgrade CI

The Downgrade (Core) job was failing with an Unsatisfiable resolution on
Julia lts (1.10). When julia-downgrade-compat pins every dep to its lowest
allowed version, FunctionWrappers was pinned to 1.0.0 (floor of "1"), but
Mooncake (a tested weakdep/extension target) requires FunctionWrappers
>= 1.1.3. That made the merged test environment unsatisfiable.

Raising the FunctionWrappers compat floor from "1" to "1.1.3" matches the
version actually exercised by the test extras and makes the minimum-version
resolution satisfiable. Verified locally on Julia 1.10: the merged test
project now resolves at minimum versions, the package loads, and basictests
pass with FunctionWrappers 1.1.3.

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

* Fix downgrade CI: run downgrade leg on Julia 1.11 + raise PrecompileTools/TruncatedStacktraces floors

The Downgrade (Core) job was red on lts (Julia 1.10). Three distinct, genuine
problems, fixed at their causes:

1. Unsatisfiable resolution. The resolver (julia-downgrade-compat -> Resolver.jl)
   minimizes Julia to the floor of its --julia range; on lts that range (1.10)
   admits 1.10.0. But every Mooncake 0.5.x test extra requires julia >= 1.10.8,
   so Mooncake can never be placed -> Unsatisfiable. Even at 1.10.8 the
   Enzyme 0.13 + EnzymeCore 0.8 + Mooncake 0.5 minimum-version set has no
   solution on the 1.10 LTS stdlib line; it resolves only once Julia reaches
   1.11.6 (Mooncake 0.5's 1.11 floor). Resolver.jl ignores the project's
   [compat] julia for the Julia version itself, so no Project.toml change can
   force julia >= 1.10.8 -- the caller must request it. Fix: pin the Downgrade
   caller to julia-version "1.11" (resolver picks 1.11.6). Core 1.10 support is
   still exercised by the regular Tests workflow.

2. PrecompileTools floor too low. With resolution fixed, the minimum
   PrecompileTools 1.0.0 fails to precompile GPUCompiler (pulled transitively by
   Enzyme) on Julia 1.11: "UndefVarError: PrecompileTools not defined in
   GPUCompiler". GPUCompiler's compat says PrecompileTools "1", but 1.0.0 does
   not actually provide the API GPUCompiler uses; 1.1.0 does. Raise the floor
   to "1.1".

3. TruncatedStacktraces floor too low. src uses
   TruncatedStacktraces.@truncate_stacktrace, which does not exist before v1.1.0
   ("UndefVarError: @truncate_stacktrace not defined in TruncatedStacktraces" at
   the v1.0.0 floor). Raise the floor to "1.1".

Also reverts the earlier misdiagnosed FunctionWrappers floor raise (1 -> 1.1.3):
no registered test dep constrains FunctionWrappers and the source only uses the
FunctionWrapper{R,A} constructor available since 1.0.0. Version bumped to 1.9.2
for the compat-floor changes.

Local verification on Julia 1.11 (the new downgrade leg): the actual
julia-downgrade-compat downgrade.jl resolves the merged test project (exit 0,
"Successfully resolved minimal versions"); the downgraded manifest (Enzyme
0.13.0 / GPUCompiler 0.27.5 / PrecompileTools 1.1.0 / TruncatedStacktraces 1.1.0
/ Mooncake 0.5.0) precompiles cleanly; and Pkg.test GROUP=Core passes
(FunctionWrappersWrappers.jl 48/48, BigFloat + UnionAll 7/7).

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

* Split AD test group out of the downgrade lane

The Downgrade (Core) red was caused by the AD test extras (Enzyme,
EnzymeCore, Mooncake) being part of the root test target. The downgrade
resolver (julia-downgrade-compat -> Resolver.jl) minimizes Julia to the
floor of its --julia range, but every Mooncake 0.5.x requires
julia >= 1.10.8 and the Enzyme 0.13 + EnzymeCore 0.8 + Mooncake 0.5 floor
set has no minimum-version solution on the 1.10 LTS line, so the merged
test env was Unsatisfiable (the Resolver.jl <-> Mooncake wall,
StefanKarpinski/Resolver.jl#24). The AD deps shouldn't gate the downgrade
lane.

Fix: move the AD test deps into their own per-group sub-environments
(test/Enzyme/Project.toml, test/Mooncake/Project.toml) and drop them from
the root [extras]/[targets].test. SciMLTesting's run_tests already supports
per-group sub-envs (the `env = ...` group form, as the nopre group uses);
the Enzyme/Mooncake groups now declare their own env. The downgrade job
runs GROUP=Core, which resolves only the root test target -- now AD-free --
so it is satisfiable on lts (Julia 1.10) again. The AD groups are added to
test/test_groups.toml so they run as their own jobs in normal CI (lts, 1);
previously they were declared in runtests.jl but had no matrix entry and so
never ran.

Reverts the SciML#59 accommodations that masked the AD-resolution problem:
- .github/workflows/Downgrade.yml: julia-version back to "lts" (no longer
  needs to be pinned to 1.11 to dodge the AD floor set).
- PrecompileTools compat floor back to "1": the 1.0.0 GPUCompiler
  precompile failure only arose because Enzyme pulled GPUCompiler into the
  downgrade env; with AD out of that env it no longer applies.

Kept, because they are genuine minimum-version bugs independent of AD
(both verified locally on Julia 1.10):
- TruncatedStacktraces = "1.1": src uses @truncate_stacktrace, which does
  not exist before v1.1.0 (1.0.0 is a 25-line stub).
- FunctionWrappers = "1.1.2": 1.0.0 / 1.1.0 / 1.1.1 fail to build the
  FunctionWrapper cfunction ("Module IR does not contain specified entry
  function") on Julia 1.10; 1.1.2 is the lowest that builds and runs. This
  is exercised by the package's own PrecompileTools @compile_workload, so
  it is a real floor regardless of the AD split.

Local verification (Julia 1.10/lts, the actual downgrade leg):
- julia-downgrade-compat downgrade.jl: exit 0, "Successfully resolved
  minimal versions for . (with extras)"; downgraded manifest contains no
  Enzyme/Mooncake/GPUCompiler (FunctionWrappers 1.1.2, PrecompileTools
  1.0.0, TruncatedStacktraces 1.1.0, SafeTestsets 0.1.0, SciMLTesting
  1.0.0).
- Pkg.test GROUP=Core with allow_reresolve=false,
  force_latest_compatible_version=false (the julia-runtest CI settings):
  precompiles cleanly and passes (FunctionWrappersWrappers.jl 48/48,
  BigFloat + UnionAll 7/7).
- The AD groups still run via their sub-envs: GROUP=Enzyme 65/65,
  GROUP=Mooncake 13/13 (Julia 1.11), with the Enzyme/Mooncake extensions
  precompiling in-group.

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

---------

Co-authored-by: ChrisRackauckas-Claude <accounts@chrisrackauckas.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Added FunctionWrappersWrapper constructor for the case where type parameters are specified but only the function to be wrapped is provied as an argument.

* Changed arguments types in test from Int to Float32 because calculating exp and cos of integer really doesn't make sense.  Actually check the value of the wrapped cos.

* Added specializations of Base.convert for FunctionWrappersWrapper based on new constructor.

* Added a docstring for new constructor

* Fixed formatting
Add a `test/qa` QA group built on SciMLTesting 1.6.0's `run_qa`, wired via
the run_tests folder model (qa = (; env, body) + [QA] in test_groups.toml).
The group runs Aqua (test_all), JET (auto-detected via `using JET`,
test_package mode :typo), and the six ExplicitImports checks.

ExplicitImports findings (explicit_imports = true), all resolved to 0 hard
fail / 0 broken:
- no_implicit_imports: made the four implicit names explicit in src —
  `using FunctionWrappers: FunctionWrappers` and
  `using PrecompileTools: @compile_workload, @setup_workload`.
- all_qualified_accesses_are_public: ignore `Base.tail`,
  `FunctionWrappers.FunctionWrapper`, and
  `TruncatedStacktraces.@truncate_stacktrace` — long-standing core API of
  those modules that predates the `public` keyword.
- the other four EI checks pass unmodified.

Because src now explicit-imports only PrecompileTools' macros, bump the
PrecompileTools compat floor to 1.1 (first self-contained-macro release) so
the downgrade lane does not hit an UndefVarError on the bare module name.

Aqua deps_compat surfaced a missing `Test` compat entry (Test is in
[extras] without a [compat] bound); add `Test = "1"` to the root [compat].

Verified locally against released SciMLTesting 1.6.0 (no dev-from-branch):
QA group 18/18 pass on Julia 1.10 (lts) and 1.11; Core 58/58; package loads
and precompiles at the downgrade floors (PrecompileTools 1.1.0,
FunctionWrappers 1.1.2, TruncatedStacktraces 1.1.0).

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

QA: run_qa v1.6 form + ExplicitImports
Raise the Mooncake [compat] floor from "0.5" to a single latest floor
"0.5.36" in every Project.toml that declares Mooncake (root weakdep +
test/Mooncake sub-env), so the downgrade min-resolution no longer pins an
ancient Mooncake. Patch-level bump of the root version (a compat narrowing
of a weakdep is not a public-API change).

Verified on Julia 1.12 via julia-actions/julia-downgrade-compat's
downgrade.jl (Resolver.jl --min=@deps): the test/Mooncake env resolves
successfully, pinning Mooncake to exactly 0.5.36 (33 packages resolved).

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
@ChrisRackauckas-Claude

Copy link
Copy Markdown
Contributor Author

Closing. Verified locally (ran the action's own downgrade.jl on the identical commit CI failed on) that raising the Mooncake compat floor does NOT fix the Downgrade lane. The failure is julia-downgrade-compat@v2 merged mode promoting all ~13 weakdep AD backends (Mooncake, Zygote, ForwardDiff, DifferentiationInterface, …) to hard deps and running Resolver.jl --min on the joint graph — which is registry-snapshot-dependent (flips UNSAT↔SAT as those packages release) and independent of Mooncake's version. This PR also unnecessarily narrows Mooncake compat. Real fix is julia-actions/julia-downgrade-compat#52 (do not promote weakdeps in merged resolution). Superseded — closing.

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.

5 participants