Repository navigation
Add __init for DynamicSS/SICNM so init() doesn't fall through to NonlinearSolve's default - #173
Draft
ChrisRackauckas-Claude wants to merge 8 commits into
Draft
ChrisRackauckas-Claude wants to merge 8 commits into
ChrisRackauckas-Claude wants to merge 8 commits into
Conversation
This was referenced Sep 23, 2026
…inearSolve DynamicSS and SICNM only had __solve; init(ssprob, DynamicSS(...)) had no matching __init here, so it fell through to NonlinearSolveBase's generic fallback, which treats "no algorithm-specific __init exists" the same as "no algorithm given" and rewrites the call to NonlinearSolve's default-algorithm converter with ::Nothing in place of the algorithm - silently discarding DynamicSS/SICNM. For a plain SteadyStateProblem that converter still finds a NonlinearProblem to solve, so init() "worked" but ignored the requested algorithm; for a SteadyStateProblem whose lowered_problem is an SCCNonlinearProblem, the converter's NonlinearProblem(prob) call hits a FieldError (SCCNonlinearProblem has no u0 field) - the reported CI failure, init(ssprob, DynamicSS(Tsit5())) in SciMLBase.jl's downstream SymbolicIndexingInterface test group. Add SciMLBase.__init(prob::AbstractSteadyStateProblem, alg::DynamicSS/SICNM, ...), mirroring the existing __solve methods (extracted into shared __dynamicss_ode_setup/__sicnm_ode_setup helpers): for a plain problem it returns the live ODE/DAE integrator so init/solve!/step! compose normally; for an SCC lowering there is no single integrator to hand back (blocks solve sequentially), so it eagerly solves via the existing __solve_scc_lowering and returns the finished solution, matching how a stored NonlinearProblem/ LinearProblem lowering is already handled verbatim elsewhere in this file. Being a more specific method than NonlinearSolveBase's generic fallback, this is picked by ordinary dispatch and the buggy conversion path is never reached for these two algorithms - independent of SciML/SciMLBase.jl#1614 (the generic converter itself is fixed separately there and in SciML/NonlinearSolve.jl#1327). Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Claude Sonnet <noreply@anthropic.com> Agent-Harness: Claude Code 2.1.251 (subagent) Agent-Model: claude-sonnet Agent-Session: https://claude.ai/code/session_01NB3oFTNzGW79UtDt8AyjsM
The comment still described SciMLBase's NonlinearProblem(::SCCNonlinearProblem) conversion as an identity that could recurse forever; it now raises an ArgumentError, and this repo's new __init methods are more specific than the default path anyway, so it is never reached. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Claude Sonnet <noreply@anthropic.com> Agent-Harness: Claude Code 2.1.251 (subagent) Agent-Model: claude-sonnet Agent-Session: https://claude.ai/code/session_01NB3oFTNzGW79UtDt8AyjsM
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Agent-Harness: Claude Code (subagent of ci-green head) Agent-Model: claude-opus-5-5[1m] Agent-Session: https://claude.ai/code/session_011aK5Xvp9NpdkzKuEwtiMGd
ChrisRackauckas-Claude
force-pushed
the
fix/init-dynamicss-sicnm
branch
from
October 7, 2026 17:10
e9bfe04 to
b7e82b4
Compare
`init(prob, ::DynamicSS/SICNM)` returned the raw ODE integrator, so `solve!` skipped the termination-condition finalization of `solve`: finite-time nonconvergence reported Success and a protective safe termination reported Terminated instead of Unstable. For SCC lowerings `init` returned a finished solution that `solve!` could not accept. `init` now returns a `SteadyStateODECache` (ODE integrator plus the setup holding the termination cache) or a `SteadyStateSCCCache`; `solve!` on either runs the same finalization as `__solve`, and `step!` advances the ODE integrator. Documents the init/solve! contract, including SICNM's extended `[y; z]` integrator state. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Agent-Harness: Claude Code (subagent of ci-green head) Agent-Model: claude-opus-5-5[1m] Agent-Session: https://claude.ai/code/session_011aK5Xvp9NpdkzKuEwtiMGd
ChrisRackauckas-Claude
pushed a commit
to ChrisRackauckas-Claude/SteadyStateDiffEq.jl
that referenced
this pull request
Oct 8, 2026
Resolves the import conflicts in src/SteadyStateDiffEq.jl and test/scc.jl, keeps both MTK init assertions, and checks that solve!(init(...)) maps the SCC solution onto the problem's state. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Agent-Harness: Claude Code (subagent of ci-green head) Agent-Model: claude-opus-5-5[1m] Agent-Session: https://claude.ai/code/session_011aK5Xvp9NpdkzKuEwtiMGd
This was referenced Oct 10, 2026
Expose symbolic state access and current parameters on DynamicSS/SICNM caches. Rebuild the integration and termination setup on reinitialization so SICNM uses the updated parameters and consistent Newton direction. Cover cache access, repeated solves, termination modes, and solution slicing in Core. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Codex <noreply@openai.com> Agent-Harness: Codex CLI 0.163.0 Agent-Model: gpt-6.1-sol Agent-Session: local session 01a157c8-4f1a-7691-afcc-019806096637 (no session URL)
ChrisRackauckas-Claude
force-pushed
the
fix/init-dynamicss-sicnm
branch
2 times, most recently
from
October 21, 2026 02:23
7dc0a12 to
e08daab
Compare
Install rebuilt cache state in one assignment so slicing, ODE-option and termination-mode overrides can change concrete types. Preserve cache identity and retain the previous state when initialization fails. Add regressions for option transitions, retained data, failed rebuilds and subsequent reuse. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Codex <noreply@openai.com> Agent-Harness: Codex CLI 0.163.0 Agent-Model: gpt-6.1-sol Agent-Session: local session 01a157c8-4f1a-7691-afcc-019806096637 (no session URL)
… cache Review (Grok, grok-4.7): clarify that step!, reinit!, and symbolic indexing are defined only on SteadyStateODECache; calling any of them on a SteadyStateSCCCache (the SCC-lowering case) throws MethodError, since only solve! is supported on it. Confirmed by running both calls directly. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Claude Sonnet <noreply@anthropic.com> Agent-Harness: Claude Code 2.1.251 (subagent) Agent-Model: claude-sonnet Agent-Session: https://claude.ai/code/session_01NB3oFTNzGW79UtDt8AyjsM
init caches forwarded :ps to a NamedTuple and had getindex without setindex!, so cache.ps[:a] and cache[:x] = value failed after the wrapper was introduced. Expose the parameter proxy, assign states through setu, and keep SICNM's residual and Newton direction consistent with live parameters after mutation. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Cursor Agent <noreply@cursor.com> Agent-Harness: Cursor Agent CLI Agent-Model: auto Agent-Session: local fixer job SciML__SteadyStateDiffEq.jl__173 (no session URL)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Please ignore until reviewed by @ChrisRackauckas.
What changed and why
GROUP=SymbolicIndexingInterfaceonSciMLBase.jlis red (CI run https://github.com/SciML/SciMLBase.jl/actions/runs/35839187919, job "SymbolicIndexingInterface (julia 1)"), fromtest/downstream/comprehensive_indexing.jl:103:init(ssprob, DynamicSS(Tsit5()); save_everystep = false)on an MTK-lowered SCC steady-state problem throwsFieldError: type SCCNonlinearProblem has no field u0.Root cause:
DynamicSSandSICNMonly had__solvehere, not__init.init(ssprob, DynamicSS(...))therefore had no matching__initin this package, so it fell through toNonlinearSolveBase's generic fallback, which — becauseDynamicSS/SICNMare notAbstractNonlinearAlgorithms — treats "no algorithm-specific__initexists" the same as "no algorithm was given" and rewrites the call toNonlinearSolve.jl's default-algorithm converter with::Nothingin place of the algorithm, silently discardingDynamicSS/SICNMentirely:For a plain
SteadyStateProblem,NonlinearProblem(prob)still finds an actualNonlinearProblemto hand off to, soinit"worked" but silently ignored the requested algorithm. For aSteadyStateProblemwhoselowered_problemis anSCCNonlinearProblem(what ModelingToolkit.jl produces for an SCC-decomposable steady-state system, SciML/ModelingToolkit.jl#5155),NonlinearProblem(prob)returns thatSCCNonlinearProblemverbatim (correct, already tested intest/scc.jl), and the secondNonlinearProblemcall — on the already-SCC result — hitsSCCNonlinearProblem's missingu0field. This is the reportedFieldError.Fix
Add
SciMLBase.__init(prob::AbstractSteadyStateProblem, alg::DynamicSS/SICNM, ...), mirroring the existing__solvemethods (the shared setup is factored into__dynamicss_ode_setup/__sicnm_ode_setuphelpers to avoid duplicating the ~40/~90 line problem-construction blocks):init/solve!/step!compose the way they do for a plainODEProblem—solve!(init(prob, alg)) == solve(prob, alg).SciMLBase.solve(::SCCNonlinearProblem, ::Union{DynamicSS,SICNM}, ...), already existing) — so it is solved eagerly and the finished solution is returned in place of an integrator, mirroring how a storedNonlinearProblem/LinearProblemlowering is already returned verbatim elsewhere in this file ("stored problem is used verbatim"in SciMLBase's own test suite).Being a method with a concretely-typed second argument (
alg::DynamicSS/alg::SICNM), ordinary Julia dispatch picks it overNonlinearSolveBase's untyped(prob::AbstractNonlinearProblem, args...)fallback, so the buggy conversion path inNonlinearSolve.jlis never reached for these two algorithms at all — this fix does not depend on SciML/SciMLBase.jl#1614 or SciML/NonlinearSolve.jl#1327 (confirmed below; those two are a separate, general-purpose hardening of the "no algorithm given" default path itself).Verification
Standalone reproducer (
init/solveon a manually-builtSteadyStateProblemwhoselowered_problemis anSCCNonlinearProblem, no ModelingToolkit needed to hit the same dispatch):Fail-before (unmodified
SciMLBase.jl+ unmodifiedSteadyStateDiffEq.jl+ unmodifiedNonlinearSolve.jl):(matches the CI trace exactly)
Pass-after (this branch + unmodified
SciMLBase.jl+ unmodifiedNonlinearSolve.jl— i.e. this fix alone, no companion PRs needed):(
u0 = [1.0]converges to the correct root-2.0ofu² = 4, confirming a real solve happened, not just an echoed initial guess)This repo's own test suite (
GROUP=Core, tail):All 427 existing assertions in
test/scc.jlstill pass unchanged (the__solverefactor into shared helpers is behavior-preserving), plus 16 new assertions added in a new"init on DynamicSS/SICNM does not fall through to NonlinearSolve's default"testset covering: a plainSteadyStateProblem(initreturns a live integrator,solve!reproduces the right answer), a manually-builtSCCNonlinearProblemlowering, and a real ModelingToolkit SCC decomposition (mirroring the existing"DynamicSS/SICNM on a SteadyStateProblem with an SCC lowering"solve-based testsets, but viainit).Runic
--checkandtyposare clean on both changed files.What I did not verify
GROUP=SymbolicIndexingInterfaceenvironment fromSciMLBase.jlitself (needs a specific newerModelingToolkit/ModelingToolkitBaseresolution); the standalone reproducer above isolates the identical dispatch chain and stacktrace without that heavy environment.GROUP=QA(Aqua/ExplicitImports).Related
NonlinearProblem(::SCCNonlinearProblem)threw an opaqueFieldError; now raises a clearArgumentErrorinstead. Not required for this PR (this PR's fix stands alone against unmodified SciMLBase).🤖 Generated with Claude Code
https://claude.ai/code/session_01NB3oFTNzGW79UtDt8AyjsM
Risk assessment
initon aSteadyStateProblemwithDynamicSSorSICNM. Code that only callssolveis unaffected, because the__solverefactor preserves behaviour: master's 411scc.jlassertions all still pass. Known downstream caller: SciMLBasetest/downstream/comprehensive_indexing.jl:103. That test only buildsssint; it never adds it tointegrators, so it only checks thatinitdoes not throw. Whatinitreturns changes:ODEIntegrator.NonlinearSolution.e9bfe04b97327d5984f8a8a349964fdbb66f1acdhas 0 commits behind masterd81bcf1818a7b3735638579ca067f070bd525c33. No check fails on either commit, so nothing needs a pre-existing comparison.Core/scc.jlgoes from 411 on master to 427 on head, so the 16 new assertions really ran. The description is wrong to call 427 the existing count.Core/autodiff.jlruns 0 tests on both commits (already true on master).solve!(init(prob, alg)) == solve(prob, alg). That is false. On a plain problem,solve!returns anODESolution, not aNonlinearSolution, and forSICNMthe state is the extended[y; z]. The new test has to slicesol.u[end][1:1]for exactly this reason.save_idxsis accepted but silently ignored in the non-SCC__initpath.initreturns a finished solution rather than an integrator. Soinitreturns a different type depending on the lowering, andsolve!/step!on that result won't work.SciMLBase.__init/__solveextension points and helpers local to the package). No tests were weakened or skipped.inithad no … dispatch, so it fell through…"). One comment says "see its docstring" but points at a plain comment, not a docstring.initsemantics (return type depends on the lowering,save_idxsdropped,solve!gives anODESolution) that a maintainer should decide on, and it partly misdescribes them.initreturns a different type depending on the lowering (integrator vs. finished solution); thesolve!(init(...)) == solve(...)claim is false;save_idxsis silently dropped in the non-SCCinitpath; the behaviour change isn't disclosed; comments are over the guideline, and the test comment is retrospective; the PR is still a draft marked "ignore until reviewed".Links
🤖 Risk assessment added by an AI agent — harness: Devin CLI 3000.11.3 · model: fusion-claude-opus-5-5-high-sidekick-swe-2-medium (independent review run as
devin -p; posted by the fleet-master session, Devin CLI / Fusion Claude Opus 5.5 Medium + SWE-2 Medium)Conversation: local, non-interactive run; output at /out-SteadyStateDiffEq.jl-173.md (no session URL)
Adopted 2026-10-07 (ci-green head)
What changed
735cb01; the original two commits keep their authorship.b7e82b4: comment trims andsave_idxshandling for the plain-probleminitpath.aabe095addresses the Codex gpt-6-astra CHANGES review (round 1):init(prob, ::DynamicSS/SICNM)now returns a cache, not the raw ODE integrator.SteadyStateODECacheholds the integrator and the setup (including the termination cache).solve!runs the same finalization assolve(termination_condition_resultretcode mapping, best-state selection, residual,save_idxs) and returns the sameSteadyStateSolution.step!(cache)advances the integrator, which is available ascache.integrator.SCCNonlinearProblemlowering,initreturns aSteadyStateSCCCache. Itssolve!runs the sequential SCC solve with the requested algorithm and keywords. Before this change,initreturned a finished solution, andsolve!on it raised aMethodError.__solveandsolve!share__steady_state_solutionand__solve_scc_lowering.__scc_lowering(prob)is factored out so the lowering is built once.docs/src/index.mdgains a section "Initialization and stepping". It documents the cache contract, including SICNM's extended[y; z]integrator state.solve!(init(prob, alg; kw...))now matchessolve(prob, alg; kw...)on retcode,uandresid. The new tests check this for every case.Verification (Julia 1.12.4; MTK 11.45.3, NonlinearSolve 4.32.0, SciMLBase#1624 dev'd, same scratch environment as the review)
init/solve! on DynamicSS/SICNM matches solveintest/scc.jlcovers plain problems,save_idxs,step!, finite-time nonconvergence (tspan = 1e-3), protectiveAbsNormSafeTerminationMode→Unstable, a manual SCC lowering (includingsave_idxsand a failing block), and an MTK SCC decomposition, for bothDynamicSSandSICNM.b7e82b4src with the new test file):scc | Pass 415 Fail 17 Error 24 Total 456. Representative failures:Evaluated: ReturnCode.Success == ReturnCode.Failure: finite tspan.ReturnCode.Terminated == ReturnCode.Unstable: protective termination.MethodError: no method matching solve!(::NonlinearSolution{…SCCNonlinearProblem…}): SCC lowering.aabe095):scc | Pass 504 Total 504.GROUP=Core(officialtest/runtests.jl), exit 0: core.jl 2322/2322, developer_interfaces.jl 5/5, precompile_workload.jl 8/8, scc.jl 504/504, sicnm.jl 33/33. autodiff.jl has 0 assertions, the same as on master.test/qa/qa.jl: Quality Assurance 21/21, Reexport surface 16/16.probes.jl(adapted to the solution-return contract) andsafe-probe.jlnow giveFINITE DynamicSS/SICNM direct=Failure staged=Failure,SAFE direct=Unstable staged=Unstable, andSCC … type=SteadyStateSCCCache, withsolve!succeeding withretcode=Success.--checkandtyposare clean on all changed files. The docs build (docs/make.jl) exits 0.Not verified locally: Julia lts, pre and x86, downgrade, and a run against registered SciMLBase without #1624. CI covers these. CI on the previous head
b7e82b4was green on all checks with registered SciMLBase.Red checks: CI on
b7e82b4and on master735cb01is all green. Checks foraabe095are pending.Stacked PR #177 needs a rebase onto this head.
src/solve.jlmerges cleanly. Theusinglines insrc/SteadyStateDiffEq.jlandtest/scc.jlconflict, and so does the tail of the MTK init testset. The conflicts are mechanical: keep both import sets, and append #177's new testset after this one.Risk assessment
init(::SteadyStateProblem, ::DynamicSS/SICNM)andsolve!/step!on its result.initnow returns a SteadyStateDiffEq cache (SteadyStateODECacheorSteadyStateSCCCache), never a raw integrator or a finished solution, andsolve!returns the sameSteadyStateSolutionassolve.solvekeeps its ODE call, and its result building moved into the shared helper unchanged; all 2322 core.jl assertions and the existing scc.jl assertions pass. No new dependencies;solve!andstep!are imported from SciMLBase likesolveandinit.initsemantics: the cache types, andcache.integratoras documented.Please ignore until reviewed by @ChrisRackauckas.
🤖 Generated with Claude Code (model: claude-opus-5-5[1m]) https://claude.ai/code/session_011aK5Xvp9NpdkzKuEwtiMGd
Fresh independent review of aabe095
CHANGES/highH1. New SteadyStateODECache wrapper removes working non-SCC public interfaces: DynamicSS/SICNM symbolic indexing, state_values, parameter_values, getsym and reinit! each error. Dependency-matched clean current base passes14/14; head2pass12errors. Preserve wrapper interfaces and reset extended state/termination caches during reinitialization; commit discriminating regressions and reconcile sibling176 semantics. Intended SCC fix independently fails2cases before and passes6checks after; Core2322/developer5/precompile8/SCC504/SICNM33/QA37/docs positive do not cover wrapper regressions. Analytic ForwardDiff sensitivity8/8 passes. Unchanged large autodiff file has0assertions and returnsFailure on both head and clean base at t367.735; separate baseline investigation queued, not a new PR regression or proof of derivative accuracy. Rewrite stale original description around final cache contract. Full downstream/merged siblings/LTS not locally tested; exact historical generic Sonnet identity remains unverified.
Risk assessment
Links:
🤖 Posted by an AI agent — harness: Codex CLI 0.163.0 · model: gpt-6.1-sol
Conversation: local session 01a154f0-8986-78e1-8af2-1119e8cdea4a (no session URL)
Assigned correction of aabe095
This correction is queued to a fresh Codex CLI worker, model
gpt-6.1-sol, under the SciML submaster’s pipeline ownership. Scope: Fresh CHANGES/H1: wrapper removes base-working non-SCC symbolic indexing/state_values/parameter_values/getsym/reinit; current-base14/14 versushead2pass12errors. Preserve both DynamicSS/SICNM interfaces and reset extended/termination state. Read sibling176/177; do not rescope them. Baseline AD fixture is separate.The revision must preserve existing assertions and demonstrate the concrete failing-before/passing-after behavior using independent references. Default-branch failures, API or compatibility-policy decisions, and unavailable hardware remain separate findings. No test suppression, unvalidated push or unrelated repair.
The worker does not merge, approve or close PRs. Any pushed revision needs a fresh independent counted review; existing source reviews are not silently repinned. This assignment does not change the PR’s risk level or resolve any finding.
Links:
🤖 Posted by an AI agent — harness: Codex CLI 0.163.0 · model: gpt-6.1-sol
Conversation: local session 01a154f0-8986-78e1-8af2-1119e8cdea4a (no session URL)
Fix by Codex gpt-6.1-sol (head e08daab)
The non-SCC
DynamicSS/SICNMcache provides symbolic state indexing,getsym,state_values,parameter_values, and the steady-state time provider. SICNM state access exposes only the steady-state variables, including whensave_idxsslices the solution.reinit!rebuilds the integrator and termination setup using the new initial state and parameters, recomputes SICNM's Newton direction, and retains initialization options. The rendered documentation describes this contract and the new integrator instance after a reset.initreturns a cache andsolve!returns the finalized steady-state solution; SCC solving and sibling initialization/state-mapping work remain separate.Executed validation
Julia 1.12.4; one Julia process at a time; four Julia threads, BLAS/OMP one thread, precompile tasks one, automatic precompilation off. All writable environments, temporary files, and the depot overlay were job-local. In the commands below,
$RUNNERis the executed wrapper fortimeout 3600 "$J" --compiled-modules=existing --check-bounds=yes; the environment and probe variables identify the isolated resolved environments and analytic sensitivity script.The identical official regression file was run against an untouched archive of head
aabe095a88153e7a0bfc0a87ad43ce0140f5a139and the corrected source, with matched dependency manifests differing only in the developed package path:Unfixed source: exit 1, with wrapper MethodErrors:
Corrected source, full official Core group: exit 0:
The default-branch interface control was also executed on clean default commit
471a4a039f637459ff8625cc832f20a7b85f4f49: the reviewer'scache-probe.jlpasses 14/14 with both algorithms. Current PR checks were all successful before this push, so there were no failed CI logs to repair;gh run view --log-failedreturned no output. Recent default CI runs inspected were successful.All exit 0. QA output:
Docs output:
Docs emitted dependency world-age warnings and the local skipped-deployment warning. The analytic
0 = p - uprobe independently checksdu/dp = 1for direct and staged solves:All exit 0 with no diagnostic output. Runic formatting was also applied in the job-local formatter environment before these checks. No dependency, exported name, existing assertion, skip, broken marker, tolerance, or warning policy changed.
G1: analytic roots
source/rateand independently evaluated residuals, plus the analytic derivative above. G2: actual in-place/out-of-place cache paths, both algorithms, stored/callable non-SCC lowerings, stepping, and the ForwardDiff direct/staged paths. G3: repeated initial-state/parameter resets, SICNM's consistent extended initial state, safe-best termination, full-state access with solution slicing, and retention of earlier solution and original problem values.Fixture control: the initial safe-best Tsit5 case returned
Stalledin both a fresh solve and a reset solve with identical state3.0000000000673706. An independent Rodas5P control returnedSuccessin both paths at3.0000000000281273. Safe-best reset coverage uses Rodas5P; default-mode reset coverage retains Tsit5. The success, root, and residual assertions remain intact.Not verified: the full SciMLBase downstream symbolic-indexing group, merged sibling branches, LTS/pre/32-bit/minimum-compatibility matrices, or GPU paths. The inherited large AD file has zero assertions and emits its solver warning; it is unchanged and is separate from the analytic sensitivity evidence. Remote CI was checked once after the push: eight jobs were in progress. No CI rerun wave, merge, approval, release, or history rewrite was performed. API/release disposition and a new independent risk rating remain with the owning review chain.
Next counted review must come from a smart model in a fresh session, not this fix session (risk.md § Independent reviews).
Links:
🤖 Posted by an AI agent — harness: Codex CLI 0.163.0 · model: gpt-6.1-sol
Conversation: local session 01a157c8-4f1a-7691-afcc-019806096637 (no session URL)
Independent review of head e08daab
Documented reinit keyword overrides fail when concrete cache fields change type; prior higher high/H1 assessment is retained for the merge decision.
Support unsliced→sliced and sliced→unsliced cache resets, introducing an ODE option such as dt, and changing termination mode for both DynamicSS and SICNM. The current concrete-field assignments throw conversion errors after partial mutation. Add discriminating official regressions and update cache state consistently; retain every existing assertion.
Other Julia versions and the sibling combined stack remain unverified. Tsit5 safe-best return-code failures reproduce in default controls; they are not attributed to this cache change. The earlier high/H1 assessment remains conservative pending correction.
Risk assessment
Links:
🤖 Posted by an AI agent — harness: Codex CLI0.163.0 · model:gpt-6.1-sol
Conversation: local session 01a154f0-8986-78e1-8af2-1119e8cdea4a (no session URL)
Fix by Codex gpt-6.1-sol (head 553252a)
Addresses the option-override blocker at
e08daab7b8f9fdb30986561719069f89160e2869. Rebuilt problem/integrator/setup/slicing/options are installed through one replaceable state reference, allowing their concrete types to change.reinit!returns the same cache object and commits that state only after initialization succeeds. Readers use one state snapshot when they need related components. The seven-argument constructor and logical properties remain available. The docstring/manual retain type-changing overrides and describe failed-rebuild behavior.The original
cache_interface.jl, including all 372 assertions and safe-best fixtures, is byte-identical toe08daab. The new officialcache_reinit_options.jlcovers adding/removing slicing, introducingdt=0.01, changing to safe-best termination and back, retaining options across resets, symbolic/full SICNM state, retained outputs/inputs, failed rebuilds, and subsequent reuse.Executed validation
Julia 1.12.4; one top-level Julia command at a time; four Julia threads; BLAS/MKL/OMP/BLIS and precompile tasks one; automatic precompilation off. Budget gates passed before work and publication. Resource guards before each Julia command checked home availability ≥200 GiB, available memory ≥40 GiB, and load ≤96. All observed checks passed. Environments, writable depot overlays and temporary files were job-local.
$RUNNERinvokestimeout 3600 "$J" --compiled-modules=existing --check-bounds=yes; environment/probe variables below name the isolated job-local artifacts.The exact frozen new test file was run against an untouched archive of
e08daaband the fixed source. Dependency manifests differ only in the developed package path:Before, exit 1 (conversion errors and inconsistent state after partial assignment):
After, full official Core group, exit 0:
All exit 0. QA and separate seven-argument construction/retained-state probe:
Docs completed doctests, document checks and HTML rendering. Dependency world-age warnings and the local skipped-deployment warning were emitted; warning policies and assertions were unchanged. Tail:
Independent analytic
0=p-u,du/dp=1probe:All exit 0, with no formatter/spelling/diff diagnostics. Formatting was applied in the local formatter environment before freezing the source and tests. Official groups ran directly through
test/runtests.jl; no parallel runner was introduced. No existing assertion, tolerance, fixture, dependency, export, version, or warning policy changed.G1: independent roots
u=p, residual zero and consistent SICNM directionz=p-u0, plus the analytic derivative. G2: both algorithms, every requested override transition, stepping, retained options, and direct/staged ForwardDiff paths. G3: unchanged cache identity, coherent failed-rebuild state, preserved earlier outputs and inputs, subsequent reuse and separate seven-argument construction.Return codes in the new repeated-reset check are compared with a fresh solve at the same operating point, alongside independent analytic root assertions. A fresh solve on published
e08daabwith Rodas5P,u0=[-2,-3],p=[6,7]returnsStalled, with residual components[1.1093970186948354e-10, 1.3867929027355785e-10]above the requested absolute threshold1e-10. This numerical stopping behavior is separate from cache option storage; it was not changed. Return-code parity checks that the requested termination mode is honored rather than silently ignored. The existing 372 assertions were not weakened.Remaining integration and review limits
The inspected sibling state-mapping diff still contains five-argument cache construction. The separate 16/16 probe checks the retained seven-argument contract; it is not a claim that the sibling tree was merged or validated. That branch's constructor update and combined-stack validation remain separate work. No sibling source was merged or changed here.
The original higher high/H1 assessment remains in force. A new independent review is required, and API/version/release disposition remains with the owning review chain. No self-authored counted review or risk downgrade is supplied.
At intake, Core/QA/docs/format/spelling/downgrade checks were successful. A separate Dependabot workflow had
startup_failurewith zero jobs ate08daab; its log request returned not found. No test-job failure was available to repair or compare, and no default parity is claimed for that startup failure. Recent default runs inspected were successful. The inherited large AD fixture still has zero assertions and its solver warning; it is unchanged and separate from the sensitivity probe.Not verified locally: the combined sibling tree, full downstream symbolic indexing, LTS/pre/32-bit/minimum-compatibility matrices, GPU paths, or completed new CI. One normal append-only push was made; the post-push check showed six jobs queued. No force push, rebase, rerun wave, merge, approval, closure, settings change or release.
Next counted review must come from a smart model in a fresh session, not this fix session (risk.md § Independent reviews).
Links:
🤖 Posted by an AI agent — harness: Codex CLI 0.163.0 · model: gpt-6.1-sol
Conversation: local session 01a157c8-4f1a-7691-afcc-019806096637 (no session URL)
Independent review of head 85dfcd0
VERDICT: CHANGES
RISK: high (H1)
SUMMARY: The SCC initialization fix works, but the new cache wrapper removes working symbolic parameter access and state assignment.
Findings
src/solve.jl:183 and src/solve.jl:205 — blocking: Preserve the existing symbolic parameter proxy and state assignment interfaces. On the merge-base,
init(prob, DynamicSS(Tsit5()))andinit(prob, SICNM(Rodas5P()))return caches supportingcache.ps[:a],cache.ps[:a] = value, andcache[:x] = value. The newgetpropertyforwards:psto a named tuple with no such field, and the wrapper implementsgetindexwithoutsetindex!. This breaks previously working callers even though read-onlycache[:x],getsym, and reset tests pass. Preserve these operations with the appropriate solver/extended-state bookkeeping and commit regression coverage for both algorithms. The unchanged 2.18.0 version does not identify a breaking release.PR body — nit: Consolidate the description around the final implementation. The original Fix/Verification sections still describe a raw integrator for ordinary problems and an eagerly computed solution for SCC problems, whereas this head returns
SteadyStateODECache/SteadyStateSCCCache. Later adoption notes supersede those statements, but leave mutually incompatible descriptions in the main body.Evidence
Independent review by Codex, model gpt-6.1-sol. Reviewed head
85dfcd0f2edda347fc1fcf5851592392fba6912e; merge-base735cb010cdf47ac93cb7def5bffda8d96dfdada7.Intended fix, fail-before/pass-after. Same analytic
4-u²=0SCC fixture and script on both trees:Base output (exit 1 because the intended-fix test fails):
Head output (exit 0):
Blocking symbolic-interface regression (finding 1), pass-before/fail-after:
Base output (exit 0, 6/6 pass on
base-working mutable symbolic interfaces).Head output (exit 1 because the six compatibility checks fail; the subsequent official SCC testsets all pass 504/504):
Risk assessment
cache.ps[:a],cache.ps[:a] = value,cache[:x] = value), reaching ordinary non-SCC initializedDynamicSSandSICNMusers.SteadyStateODECachesymbolic indexing and parameter proxy access insrc/solve.jl.🤖 Posted by an AI agent — harness: Codex CLI · model: gpt-6.1-sol (independent reviewer; appended by Antigravity CLI · model: gemini-4-argon-high)
Conversation: local job oss-reviews-2026-10-21-SciML-SteadyStateDiffEq-173 (no session URL)
Fix by Cursor auto (head 439c8c5)
Restores the merge-base symbolic parameter proxy and state assignment interfaces on
SteadyStateODECacheforDynamicSSandSICNM.cache.psreturnsSymbolicIndexingInterface.ParameterIndexingProxy(cache);:psis included inpropertynames.cache[sym] = valueusessetuand marks the integrator modified viaSciMLBase.derivative_discontinuity!(the current name of the review'su_modified!notify).gnow takes live parameters from the integrator. Aftercache[:x] = valueorcache.ps[:a] = value, the algebraic direction is recomputed asz = -J(y)⁻¹ g(y)and refreshed again beforestep!/solve!when the integrator is marked modified.test/cache_interface.jlcover bothDynamicSS(Tsit5())andSICNM(Rodas5P())(iip and oop):cache.ps[:a],cache.ps[:a] = value,cache[:x],cache[:x] = value, SICNM consistentz, andsolve!reflecting the mutated operating point. No@inferredongetu(prob, :x)(cache).The original PR Fix/Verification text still describes an earlier integrator/eager-solution contract. Later adoption notes and this section describe the current cache types; the original body was not rewritten here.
Fail-before / pass-after (interface probe)
Unfixed head
85dfcd0(6/6 fail):After this commit (6/6 pass):
Executed validation
Runic
--checkandtyposexited 0 with no diagnostics.Official Core (Julia 1.12.4), exit 0:
Official QA: Aqua, ExplicitImports (6/6 after accessing
ParameterIndexingProxyfrom SymbolicIndexingInterface), public-API docs, and reexports passed. JETmode=typothrewIOError: FolderMonitor (start): too many open files (EMFILE)on two isolated retries under host file-watcher load. That is not a code finding; CI QA on the previous head was already green.Docs completed doctests, document checks, and HTML rendering:
No existing assertion, skip, broken marker, or warning policy was changed. No
@inferredwas added ongetu(prob, :x)(cache).Next counted review must come from a smart model in a fresh session, not this fix session (risk.md § Independent reviews).
🤖 Posted by an AI agent — harness: Cursor Agent CLI · model: auto
Conversation: local fixer job SciML__SteadyStateDiffEq.jl__173 (no session URL)
Risk assessment (independent review, Codex CLI (gpt-6.1-sol), local job oss-reviews-2026-10-21-SciML-SteadyStateDiffEq-jl-173 (no session URL), head 439c8c5)
439c8c5078c0and rated it high (H1), high confidence, verdict CHANGES.Executed review notes (head 439c8c5)
VERDICT: CHANGES
RISK: high (H1)
SUMMARY: SCC initialization is fixed, but the new cache breaks keyword-based reinitialization and can reuse a stale initial state.
Findings
src/solve.jl:279 — blocking: Preserve the existing
reinit!(cache; u0=..., p=...)interface. The new method only consumes positionalu0; keywordu0lands inkwargs, bypassesremake, and reaches the ODE initializer. For SICNM, this replaces the extended[y; z]initial state with the caller'syvector and throwsMass matrix size is incompatible with initial condition sizing. For DynamicSS, the first keyword reset appears to work, but storesu0among the persistent initialization options: afterreinit!(cache; u0=[-3.0], p=[4.0]), a subsequentreinit!(cache, [7.0]; p=[8.0])still starts at[-3.0]. The identical sequence passes on the merge-base for both algorithms. Consume and normalize keywordu0before rebuilding the problem, keep it out of the stored ODE options, and add keyword-then-positional reset regressions for both algorithms. The PR's reset tests use positionalu0, so they miss this compatibility regression. Retaining version 2.18.0 does not designate a breaking release; preserve the working interface.pr.json:1 (body, original “Fix” and “Verification” sections) — nit: Rewrite the description around the final implementation. Those sections still promise a raw integrator for ordinary problems and an eagerly computed solution for SCC problems. The reviewed head returns
SteadyStateODECacheandSteadyStateSCCCache, respectively. Later appended corrections describe that contract, but leave contradictory claims in the main description.Evidence
Independent review of head
439c8c5078c07e5aa002b037e309f756f990c0a2against merge-base735cb010cdf47ac93cb7def5bffda8d96dfdada7, using Julia 1.12.7. No edits, commits, pushes, or GitHub posts were made in/fromrepo.Risk assessment: Before reading the PR body, the diff was provisionally medium (M1). The demonstrated compatibility regression raises it to high (H1), the highest matching criterion. Matching criteria: L1 (documentation), L2 (added assertions without weakening existing ones), L7 (shared setup/finalization refactor under 400 changed non-test source lines), ML8 (cache state/reset bookkeeping with tests), M1 (new methods on SciMLBase interfaces and changed
initdispatch/return contract), and H1 (previously accepted reinitialization inputs now error or select the wrong initial state). The affected lane is non-SCCinit/reinit!with DynamicSS or SICNM; the SCC initialization fix itself is independently reproduced.Scratch trees were created with:
Only scratch project metadata was expanded to include the existing test extras. After
Pkg.resolve()/Pkg.instantiate(), the same Project.toml and Manifest.toml were used on both trees. Both loaded SciMLBase 3.58.0 and NonlinearSolve 4.32.0. The head source checksum matches the untouched checkout.Intended fix, failing on base and passing on head:
The discriminating test initializes and solves an SCC lowering with residual
4 - u^2, initial state[1.0], and independent expected root[2.0].Base, exit 1:
Head, exit 0:
Blocking regression, passing on base and failing on head:
The fixture is
SteadyStateProblem((u,p,t)->p .- u, [0.0], [2.0]); each algorithm receives the same keyword reset to[-3.0], followed by the same positional reset to[7.0].Base, exit 0:
Head, exit 1:
Independent derivative checks:
For
f(u,p)=p[1]-2u, the analytic steady state isp[1]/2and its derivative is0.5. All eight explicit derivative assertions pass on each tree: both algorithms, in-place/out-of-place, directsolve/stagedsolve!(init(...)). Head output:The head follow-up process exits 1 because its subsequent keyword-reset test reproduces finding 1; the base follow-up exits 0. The exploratory probes also exposed scalar-assignment and post-termination mutation limitations on the base, which are not counted as introduced regressions.
Official Core runner, exit 0, 3,590 assertions pass:
The unchanged
autodiff.jlfixture logs a NaN error estimate and aborts integration att=367.7350295054817, while its zero-assertion testset remains green. This also occurs on the base; it is not an introduced regression. Independent baseline check, exit 0:Relevant real output:
Static/CI checks:
git -C repo diff --numstat <base> HEADshows no dependency, compat, version, or license changes. All imported packages were already dependencies; the package retains its MIT license. Existing assertions/tolerances/skips are preserved. The new tests include analytic equilibrium/residual checks rather than relying solely on equality between two paths sharing implementation. The suppliedpr.jsonreports 13 checks, allSUCCESS, including Core, QA, docs, downgrade, and benchmarks; this is supplied CI metadata, not a local rerun of each job.test/autodiff.jlstill has no assertions, as on base, so its successful execution alone does not demonstrate derivative accuracy.Not verified
🤖 Posted by an AI agent — harness: Codex CLI · model: gpt-6.1-sol (independent reviewer; appended by Antigravity CLI · model: gemini-4-argon-high)
Conversation: local job oss-reviews-2026-10-21-SciML-SteadyStateDiffEq-jl-173 (no session URL)