Repository navigation
Map SCC-lowered steady-state solutions back onto the problem's state (stacked on #173) - #177
ChrisRackauckas-Claude wants to merge 11 commits into
Conversation
…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
A `SteadyStateProblem` built by ModelingToolkit records an SCC lowering that is compiled from the residual system separately, so its state can differ from the problem's in length and order (for a `complete`d but uncompiled system, `mtkcompile` can eliminate unknowns as observed). `DynamicSS`, `SICNM` and `SSRootfind` returned the lowering's solution as-is, so `sol.u` no longer lined up with `prob.u0` and indexing by the system's variable indices failed with a BoundsError (SciMLBase test/downstream/comprehensive_indexing.jl). When the problem is symbolic and the lowering resolves every unknown of the problem, the solution is now built on `prob` in its own state ordering, with the SCC solution kept as `original`. Problems without symbolic information keep the solution on the lowering. 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
`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
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
The mapped state is converted to `typeof(prob.u0)`, so an observed
integer literal no longer yields a `Vector{Int}` for a Float64 problem.
The mapped solution carries the lowering solution's `stats`, `left` and
`right`, and a `save_idxs` slice keeps the unsliced solution as
`original`.
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
ModelingToolkit 11.44 cannot build an SCC lowering for a system whose unknowns are all eliminated (empty `var_sccs`); 11.45.0 handles it, so the ModelingToolkit test compat floor moves to 11.45. At the floor NonlinearSolve stack, Newton cannot form a Jacobian for the resulting zero-length problem, so the eltype check uses Jacobian-free `Broyden`. 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
Independent review (Devin CLI 3000.11.3, model fusion-claude-opus-5-5-high-sidekick-swe-2-medium): MERGE, risk medium. Full reviewVERDICT: MERGE Merge only after #173 lands: this PR is stacked on it. The risk is medium because Blocking findingsNone. Non-blocking findings
What I ranAll runs used Julia 1.12 against registered packages, not the author's dev'd SciMLBase#1624: SciMLBase 3.57.0, ModelingToolkit 11.45.3, NonlinearSolve 4.32.0, SCCNonlinearSolve 1.15.4, SymbolicIndexingInterface 0.3.55, OrdinaryDiffEq 7.8.1. There were two envs,
What I did not verify
Links:
🤖 Posted by an AI agent — harness: Devin CLI 3000.11.3 (review), Claude Code 2.1.285 (posting) · model: fusion-claude-opus-5-5-high-sidekick-swe-2-medium |
Restore mapped values in the original state's geometry before converting its container type. Exercise scalar, matrix and tensor states across all three algorithms, including original residuals, output selection and cache isolation. Document the mapped solution and fallback contract in the algorithm docstrings. 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 01a15cba-455f-7840-a71e-61b5d3b9fca9 (no session URL)
Allocate mapped arrays through map in the original geometry and convert each mapped value to the original element type. Cover views across all three algorithms, residual conventions, output slicing and repeated cached solves. Document the allocation contract and retain container coverage in repository instructions. 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 01a15cba-455f-7840-a71e-61b5d3b9fca9 (no session URL)
Order symbols by their original state indices before retrieving lowered solution values, using the original array geometry for Cartesian indices. Cover independent enumeration and lowering permutations, strided views, original residuals, and repeated cached slicing with analytic roots. 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 01a15cba-455f-7840-a71e-61b5d3b9fca9 (no session URL)
Please ignore until reviewed by @ChrisRackauckas.
Stacked on #173 (#173's commits are included here, now up to its head
aabe095via a merge commit; review onlyMap SCC-lowered steady-state solutions back onto the problem's stateand the merge resolution). Merge #173 first.What changed and why
Since 2.17/2.18, a
SteadyStateProblembuilt by ModelingToolkit carries an SCC lowering (SciML/ModelingToolkit.jl#5155), andDynamicSS/SICNM/SSRootfindsolve through it (#166, #169). The lowering ismtkcompile(NonlinearSystem(sys)), a separately compiled system whose state can differ from the problem's in length and order. The returned solution was built on the lowering, sosol.uno longer matchedprob.u0. For acompleted (uncompiled) two-state ODE system, the lowering keeps 1 unknown (X) and makesYobserved, sosol.u == [5.0]whileprob.u0has 2 entries. Anything that indexes the solution by the system's variable indices then fails. That includes SciMLBase'stest/downstream/comprehensive_indexing.jl:128/165(BoundsError), which keepstests / SymbolicIndexingInterfacered on SciMLBase master and downstream in SymbolicIndexingInterface.jl and ModelingToolkit.jl. It also breaks the commonODEProblem(sys, ...; u0 = sssol.u)pattern.The fix is in SSDE because SSDE builds the returned solution. The lowering is an internal solve strategy, so
solve(prob)should return a solution ofprob.__scc_solution_on_problemmaps the SCC solution back when two conditions hold:prob.fhas asys, and the lowering's index provider resolves everyvariable_symbols(prob)(as a variable or observed). It then rebuilds the solution onprobinprob's ordering. It recomputesresidasprob.f(u, p, Inf)and keeps the SCC solution assol.original.save_idxsnow indexesprob's ordering. A problem without symbolic information (a hand-builtlowered_problem) has no mapping, so its solution stays on the lowering, as before. This applies toDynamicSS,SICNMandSSRootfind, and toiniton an SCC lowering from #173.MTK and SciMLBase need no change. Symbolic indexing (
sol[x]) already worked on the lowering-based solution and still works. Only the state vector and its index provider change.Behaviour change (reviewer: push back here if you disagree)
For an MTK-built
SteadyStateProblemwith an SCC lowering,sol.probis now the (concretized)SteadyStateProblem, not theSCCNonlinearProblem, andsol.originalis the SCC solution. Five existing assertions intest/scc.jlencoded the old choice (sol.prob isa SCCNonlinearProblem). They now assertsol.prob isa SteadyStateProblem,length(sol.u) == length(prob.u0)andsol.original.prob isa SCCNonlinearProblem. Every symbolic-value assertion is unchanged. MTK's own test (test/scc_nonlinear_problem.jl:665) already assertssol.prob isa SteadyStateProblemforDynamicSS.Verification
New testset
SCC-lowered solution is expressed in the problem's state(DynamicSS, SICNM, SSRootfind): on acompleted 2-state system whose lowering has fewer unknowns, it checkslength(sol.u) == 2,sol.u[variable_index(osys, [X, Y])],getsym(osys, [X, Y])(sol), observedsol[XY],resid ≈ 0, andsave_idxs.test/scc.jlrun in an env with SciMLBase#1624 dev'd, MTK 11.45.3 and NonlinearSolve 4.32.0:b7e82b4src, this PR's tests):scc | Pass 434 Fail 13 Error 17 Total 464. The failures are the new testset and the updated assertions, e.g.Expression: sol.prob isa SteadyStateProblemandDimensionMismatchonsol.u[uidxs].97da160):scc | Pass 464 Total 464.Standalone MTK repro (the
ssprobfrom SciMLBase's comprehensive_indexing.jl):Runic
--checkandtyposare clean on the changed files.SciMLBase
GROUP=SymbolicIndexingInterfacewith all branches dev'd together. SciMLBase#1624 head717d1123, SSDE at this branch97da160(includes #173), MTK 11.45.3, Julia 1.12, run asGROUP=SymbolicIndexingInterface julia --project -e 'using Pkg; Pkg.test()':Update 2026-10-08: merged #173 head
aabe095#173 now returns
SteadyStateODECache/SteadyStateSCCCachefrominit, andsolve!on them gives the same solution assolve. Merge commit2542436brings that into this branch with no rebase and no force push. Only imports conflicted, insrc/SteadyStateDiffEq.jlandtest/scc.jl, plus the tail of the MTK init testset; both sides were kept.src/solve.jlmerged cleanly. The SCC cache'ssolve!goes through__solve_scc_lowering, so it maps ontoprobin the same way. The new state-mapping testset now also checkssolve!(init(prob, alg))for DynamicSS/SICNM (sol.prob isa SteadyStateProblem,sol.u[uidxs] ≈ [Xss, Yss]).Verification at
2542436(Julia 1.12.4; SciMLBase#1624 headb18f1fc3dev'd; MTK 11.45.3; NonlinearSolve 4.32.0):GROUP=Core(test/runtests.jl) exit 0:test/qa/qa.jl: Quality Assurance 21/21, Reexport surface 16/16.--checkandtypos: clean.GROUP=SymbolicIndexingInterfacewith SciMLBase#1624 and this branch dev'd.Pkg.test(), exit 0:The Broken counts are pre-existing
@test_broken. This PR adds none.Update 2026-10-08: Grok 4.7 review round 1 (CHANGES): three blocking findings fixed in
9a99d5aEltype. The mapped state is now
convert(typeof(prob.u0), collect(u)). Before, an observed integer literal returnedVector{Int64}for aFloat64problem.Stats. The mapped solution now carries the lowering solution's
stats,leftandright, as__build_ssrootfind_solutiondoes. Before,SSRootfindreturnedstats = nothingafter mapping.save_idxsoriginal. Asave_idxsslice now setsoriginal = sol, the unsliced solution:Before,
originalwas one level too deep (the per-block tuple, or the SCC-order state only).New testset
SCC-lowered solution metadataintest/scc.jl:SSRootfind,DynamicSSandSICNMon acompleted one-state system whose lowering observesx = 1.stats,leftandrighton the reordered Lotka–VolterraSSRootfindsolve.save_idxs→.original, on a manual two-block SCC and on a symbolic linear system.Both runs below use the standalone testset with this PR's environment.
2542436src):SCC-lowered solution metadata | Pass 16 Fail 5 Error 3 Total 24. Representative failures:Evaluated: [1] isa Vector{Float64}and[0] isa Vector{Float64}nothing !== nothingandnothing === SciMLBase.NLStats(4, 4, 4, 4, 4)sliced.original.prob isa SteadyStateProblemevaluated toSCCNonlinearProblem…; the.original.uchecks errored.9a99d5a):Pass 24 Total 24.Verification at
9a99d5a(Julia 1.12.4, SciMLBase#1624b18f1fc3dev'd, ModelingToolkit 11.45.3):GROUP=Coreexits 0:QA: Quality Assurance 21/21, Reexport surface 16/16.
Runic and typos: clean.
SciMLBase
GROUP=SymbolicIndexingInterfaceis rerun because the mapping path changed, and exits 0:The review's non-blocking notes are not addressed here, because each is outside this PR's scope:
solve(prob)andsolve(prob, NewtonRaphson())still return the lowering. They take the NonlinearSolve path, so issue solve(::SteadyStateProblem) returns the lowered problem's solution: sol.u reordered/empty, sol.prob.f.sys time-independent #171 stays open.SSRootfindignoressave_idxs(pre-existing).DynamicSSfails at a center equilibrium. That is a non-SCC lowering, unaffected by the mapping.Update 2026-10-09: Downgrade fix in
dc54954CI
test / Downgrade Testsfailed on9a99d5a(https://github.com/SciML/SteadyStateDiffEq.jl/actions/runs/37858191872/job/113587359583):scc.jlreported 555 pass and 3 errors.Cause. The eltype testset's system has every unknown eliminated, so its SCC lowering is empty. ModelingToolkit 11.44.0, the old test floor, throws
MethodError: no method matching ModelingToolkit.SCCDecomposition(::System, ::Vector{Vector{Int64}}, ::Vector{Any}; combine_sccs::Bool)on it. 11.45.0 added theisempty(var_sccs)branch insrc/problems/sccnonlinearproblem.jl.Fix (no test skipped or version-guarded):
ModelingToolkitcompat floor goes from11.44to11.45. ModelingToolkit is a test-only[extras]dependency, so users are not affected.chunk size cannot be greater than ForwardDiff.structural_length(x) (1 > 0). The eltype check therefore uses the Jacobian-freeSSRootfind(Broyden()). The mapping bug that this test targets is independent of the algorithm.Verification
julia-actions/julia-downgrade-compatat the CI SHA (downgrade.jl … "." "deps" "1" "Mooncake", Resolver--min=@deps, Julia 1.10.12). It reportsSuccessfully resolved minimal versions … (with extras), with ModelingToolkit 11.45.0, ModelingToolkitBase 1.77.0, SciMLBase 3.55.0, NonlinearSolve 4.21.0, NonlinearSolveBase 2.49.4, OrdinaryDiffEq 7.2.1, Symbolics 7.39.2, SymbolicIndexingInterface 0.3.47, SCCNonlinearSolve 1.13.0 and DiffEqBase 7.18.1.GROUP=Corein that environment (Julia 1.10,Pkg.test(allow_reresolve=false)) exits 0:Broydeneltype check:2542436source:Pass 16 Fail 5 Error 3 Total 24, including[1] isa Vector{Float64}forSSRootfind.Pass 24 Total 24.#173 is unaffected: its branch does not contain this testset or the compat change, and its Downgrade check was green.
Not verified locally
test/scc_nonlinear_problem.jlwith this branch. Its assertions are symbolic (sol[x]) orsol.prob isa SteadyStateProblem, so it should be unaffected, but I did not run it.Risk assessment
solve/initofSteadyStateProblems that carry an SCC lowering (MTK-built only) withDynamicSS/SICNM/SSRootfind:sol.u,sol.residandsol.probmove from the lowering's coordinates back to the problem's. Problems without a lowering, or without symbolic information, are unchanged. This reverts the coordinate choice that 2.17/2.18 introduced, so anyone who relied onsol.prob isa SCCNonlinearProblem(only this package's own tests, as far as I found) sees a change.tests / SymbolicIndexingInterfacetogether with SciMLBase#1624 and SSDE#173.🤖 Generated with Claude Code (model: claude-opus-5-5[1m]) https://claude.ai/code/session_011aK5Xvp9NpdkzKuEwtiMGd
Risk assessment (independent review, Codex gpt-6.1-sol, head dc54954)
Verdict: CHANGES
Rating: Codex gpt-6.1-sol rated it high (H1) at head dc54954
Risk: high (H1: changes the documented problem and state ordering returned by published algorithms, including
sol.prob,sol.u, andsol.original; the risk policy explicitly identifies this PR as an H1 example).Blast radius: Symbolic steady-state problems with stored lowerings solved using
SSRootfind,DynamicSS, orSICNM, including positional indexing, residuals,save_idxs, and consumers of solution metadata. The included stack also changesinit/solve!and introduces persistent ODE/SCC caches. The scalar regression affects a symbolic original problem with a scalar initial state and a vector-valued nonlinear lowering.Evidence: Read the full
git diff origin/HEAD...HEAD, the issue and stack description, public dependency declarations, and licenses. Default source snapshot:471a4a039f637459ff8625cc832f20a7b85f4f49; head:dc54954c57c221daaa3efec71a5f0fd5d8fc8fda. All execution used scratch source copies and one Julia process at a time, Julia 1.12.4,JULIA_NUM_THREADS=4, the requested depot path, and hour-long timeouts. Both environments use ModelingToolkit 11.45.3, NonlinearSolve 4.32.0, and SciMLBase 3.57.0.With
S=<local path>, rantimeout 3600 julia --project="$S/env" --compiled-modules=existing "$S/run-targeted.jl": 54/54 pass, exit 0. This extracts only the two newly added mapping/metadata testsets from head. Ran the identical tests against base usingtimeout 3600 julia -O0 --compiled-modules=existing --project="$S/base-env" "$S/run-targeted.jl": 27 pass, 8 fail, 13 errors, exit 1, including the problem-type assertion and positional-indexing errors. These are intentional negative-control failures in the new tests, not evidence of unrelated failures in the existing default-branch suite. Logs: head, base.Ran
timeout 3600 julia -O0 --compiled-modules=existing --project="$S/base-env" "$S/scalar.jl"and the same command with--project="$S/env": base 2/2 pass, exit 0; head 1 error, exit 1, withCannot convert Vector{Float64} to Float64at line 137. Reproducer: scalar.jl; logs: base, head.gh pr checks 177 --repo SciML/SteadyStateDiffEq.jlreports no failing current-head checks; the Core job log confirms 567/567 SCC assertions. There is no current failing CI check to classify as pre-existing.git diff --check origin/HEAD...HEADis clean. No new runtime dependency, copyleft dependency, skipped test, or loosened numerical tolerance was found; SymbolicIndexingInterface is already a runtime dependency and is MIT licensed. Newly accessed dependency names are public at their owners; no new package-owned public name is introduced.G1: pass — the mapping test checks the state against an independently assembled linear-system solution and checks the original residual against zero. G2: not applicable — no GPU kernels, custom AD rules, Reactant tracing, or MPI implementation changes; the existing ForwardDiff calculations inside SICNM execute in the targeted tests. G3: pass — the included cache tests exercise stepping before completion, termination/failure codes, and
solve!(init(...))versus direct solve; current SCC CI runs them, and the local mapping test also exercises the SCC cache path.Merge: needs changes (fix scalar-state restoration, establish H1 major-release handling, and update the three public algorithm docstrings). High risk requires Chris's release decision even after technical findings are resolved.
🤖 Posted by an AI agent — harness: Codex CLI 0.162.1 · model: gpt-6.1-sol
Conversation: local headless review run (no public session URL); transcript kept by the fleet master.
Fresh independent review of dc54954
CHANGES/highH1. Original scalar/matrix initial states throw during mapped solution restoration: Vector-to-Float64 and Vector-to-Matrix conversion errors at src/solve.jl:137. Identical public-API analytic-root probes succeed with4/4 state-type assertions on dependency-matched clean current master. The intended mapping tests pass54/54 on head but discriminate against base. Reconstruct original shape/container and add regressions. Rendered SSRootfind, DynamicSS and SICNM docstrings still promise lowering order, contradicting the implemented original-state mapping; document actual state/residual/save_idxs/original/fallback behavior. Public output contract and version2.18.0 require Chris major-release decision. Independent Core2412, developer5, precompile8, SCC567, SICNM33 and unchanged QA/format40 pass; docs builds. Existing autodiff file contains0assertions and solver warnings, so no derivative-accuracy claim. Prerequisite initialization PR173 remains open; no merge before prerequisites, code repair and Chris decision. Review intake retained prior labels; fresh executed evidence supports findings.
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 dc54954
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: scalar/matrix original states error in restoration atsolve.jl137 whilecurrentbase4/4passes; fixshape/container preservingmapping54cases and originalresidual/save_idxs semantics. Correct rendered three algorithm docstrings. API/release decision remains Chris; noversion/tag/release. Prerequisite173 staysseparate.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 8f443af)
Mapped scalar states retain their scalar type. Array states are reshaped to the original geometry before conversion to the original container type. The three rendered algorithm docstrings describe original-state mapping, original residual evaluation,
original, symbolic-mapping fallback, and output selection, including the existingSSRootfindlimitation.Added 395 assertions covering all three algorithms, scalar/matrix/tensor states, in-place and out-of-place residuals, reversed symbolic ordering, failed solves,
save_idxs, and mutation isolation across repeated cached solves. All 567 existing SCC assertions also pass. No dependency, compat, version, tag, or release change.Executed validation
Sdenotes private scratch storage. The job-localrun-julia.shinvokestimeout 3600 julia +1.12.4, sets four Julia threads, one BLAS thread, one precompile task, a private temporary directory and writable depot overlay, and uses existing depots as fallbacks. Only one top-level Julia command ran at a time; the unchanged official Pkg/Aqua harness spawned its required children while parents waited. The before/after environments use the same dependencies (SciMLBase 3.57.0, ModelingToolkit 11.45.3, NonlinearSolve 4.32.0).Discriminating regression. The probe extracts the final regression testset from
test/scc.jl; its assertion body matches the official testset modulo Runic formatting. Unfixed source is an untouched archive of dc54954.Before, exit 1:
The failures are scalar, matrix and tensor restoration errors. After, exit 0:
The review's public-API scalar/matrix analytic-root control was also executed against clean current default 471a4a0 with matched dependencies:
Official groups, both exit 0:
The autodiff file contains zero assertions; this is not derivative-accuracy evidence.
Documentation, formatting and spelling, all exit 0:
Deployment was skipped outside CI. A separate HTML inspection confirms the state/container, original-residual and fallback contracts in all three rendered algorithm docstrings, the unsliced-original contract in both integration algorithms, and the
SSRootfindoutput-selection limitation. Runic, typos over added diff lines, and whitespace checking produced no output.G1: analytic roots and independently written original residuals. G2: the changed restoration paths execute for all three algorithms, both original-residual calling conventions, and both plain and SCC lowerings. G3: mutate a returned unsliced state, solve the same cache again, and assert the new result and original initial state remain correct. No skipped/broken tests, swallowed errors, relaxed tolerances, or warning-only build configuration were added.
Current-head CI had no failing test check at intake; current default's Core/QA/downgrade/docs checks were green. The historical downgrade failure log was read; its corrected current-head run is green. No unrelated baseline repair was included. Not verified locally: LTS/32-bit/pre-release/downgrade matrices or downstream packages. Remote CI after this push is not claimed complete.
Remaining gates
Risk remains high (H1): the public output-contract/release decision remains pending, and the initialization prerequisite remains separate. This correction does not make a release or merge decision.
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 01a15cba-455f-7840-a71e-61b5d3b9fca9 (no session URL)
Independent review of head 8f443af
Independent executed probes find a remaining view-backed initial-state restoration regression; existing public-contract risk remains high.
At8f443af3, view(zeros(2,2),1:1,:) with analytic equilibrium[2,3] solves on cleanmaster for allthreealgorithms(base6/6), but headthrows3Matrix-to-SubArray conversionerrors atsolve.jl140. Reconstructoriginalgeometry withoutaliasingprob.u0, supportviews acrosssolve/init/solve!, preserveoriginalmapping/residual/save_idxs/failure contracts andrendereddocs. No lowered-order fallback.
Findings-only, NOT a counted merge rating: reviewer disclosed priorlabels leaked through supplied intake. Rawfinding/probes arefreshsession distinctfromauthor, but completeblinding notclaimed. Headincludes173onlyaabe095; latest553combinedstacknotverified. H1publicoutputcontract/releasedecision remainsChris; localLTS/pre/x86/downgrade/downstreamcorpusunverified.
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 f2fa91e)
View-backed initial states now map into independent array storage in the original geometry. Array reconstruction uses
mapon the original state and converts each mapped value to its element type, avoiding conversion of a dense result into a concreteSubArray. Scalar restoration, symbolic ordering, original residual evaluation, metadata, and slicing/cache contracts retain their regression coverage. All three rendered algorithm docstrings describe the actual allocation contract. Repository instructions record the repeated container-reconstruction constraint.The expanded official testset retains all 395 previous assertions and adds 528 view assertions, covering all three algorithms, four matrix/tensor shapes, both original-residual calling conventions,
save_idxs, applicableinit/solve!paths, and isolation from the view/backing storage and earlier cached solutions.Executed validation
Sdenotes private scratch storage.view-run-julia.shinvokestimeout 3600 julia +1.12.4, explicitly sets four Julia threads, BLAS/OMP/MKL threads to one, one precompile task, a job-local temporary directory and writable depot overlay, and existing depots as fallbacks. One top-level Julia command ran at a time; the unchanged official Pkg/Aqua harness used its required child processes while parents waited. The matched before/after control and Core environment use SciMLBase 3.58.0, ModelingToolkit 11.45.5, NonlinearSolve 4.32.0, and SymbolicIndexingInterface 0.3.55.Discriminating official regression: the probe extracts the final official testset; its assertion body matches
test/scc.jlmodulo Runic formatting. The unfixed source is an untouched archive of the parent commit linked below.Before, exit 1:
All 24 view variants error during dense-array-to-SubArray restoration; the 395 prior assertions pass. After, exit 0:
The exact executed finding's
view(zeros(2,2), 1:1, :)analytic-root probe also passes 6/6 on clean current default and 6/6 on this correction, with matched dependencies and unchanged assertions/tolerances:Official Core and QA, both exit 0:
Core totals 3948 passing assertions, including 1490 SCC. The existing autodiff file has zero assertions, so this is not derivative-accuracy evidence.
Docs, formatting and spelling, all exit 0:
Deployment was skipped outside CI. HTML inspection confirms all 3/3 algorithm docstrings describe independent view storage, shape/order, original residuals and symbolic fallback; both integration algorithms describe unsliced
original, andSSRootfind's selection limitation is retained. Runic, typos over the added diff and instruction file, and whitespace checks produced no output.G1: analytic equilibria and independent original-residual checks. G2: all three solve paths, in-place/out-of-place original residuals, matrix/tensor views, and applicable initialized caches execute. G3: storage-alias checks plus mutation/repeated-solve assertions establish isolation from initial/backing storage and earlier results. No skipped/broken tests, loosened tolerances, swallowed exceptions, or warning-only configuration; no new source comments, runtime dependency, compat or version change.
Remaining gates
The supplied executed review is findings-only, not a counted merge rating because of its disclosed intake-label exposure. This fix makes no independent-review or merge decision. H1 public-contract/release policy remains unresolved. The tree includes the initialization prerequisite only through the commit linked below; newer prerequisite revisions and the combined stack are neither integrated nor approved/validated here. No version/tag/release/merge/settings action.
Current-head intake checks and latest-default test CI were green; no unrelated baseline repair was included. Not verified locally: LTS/pre-release/32-bit/downgrade matrices, downstream corpora, derivative accuracy, or the newer combined prerequisite tree. Remote CI completion after this push is not claimed.
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 01a15cba-455f-7840-a71e-61b5d3b9fca9 (no session URL)
Executed findings at head f2fa91e — session 01a15db3-9dcf-7713-b93d-599577e39b55
Reconstructing state in symbol-enumeration order can return the wrong successful solution. The public indexing interface permits symbol enumeration to differ from variable indices. With an otherwise valid provider enumerating
[:y, :x]while indices remainx=1, y=2, the independent root is[2, 3]; all three algorithms instead return approximately[3, 2], original residual[-1, 1], andSuccess. The exact matched-dependency probe passes6/6 on clean base and fails0/6 on this head. Use the original provider'svariable_indexto place values, preserve state geometry/view isolation, and add this counterexample permanently.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)
Fix by Codex gpt-6.1-sol (head ddb3e7c; session 01a15cba-455f-7840-a71e-61b5d3b9fca9)
Mapped values now follow the original provider's public
variable_index, normalized throughLinearIndicesin the original geometry.variable_symbolsenumeration is copied and ordered by these indices before retrieving lowered values. Array allocation, original residual evaluation, metadata and slicing/cache behavior retain their existing implementation.The permanent official regression exercises all 36 independent enumeration/lowering permutation pairs across three shapes, linear and Cartesian indices, dense arrays and reversed strided views, both residual calling conventions and all three algorithms: 2,592 cases, 65,664 assertions. Applicable initialized solves check
save_idxs, fulloriginalstates, mutation isolation and repeated caches. Expected roots are independently specified as[2, 3, 5]. The existing 923-assertion container testset is byte-for-byte unchanged.Executed validation
Sdenotes private scratch storage. The local wrapper runs Julia 1.12.4 withtimeout 3600, four Julia threads, BLAS/OMP/MKL threads set to one, one precompile task, and job-local temporary storage and writable depot overlay. One top-level Julia command ran at a time; the unchanged official Pkg/Aqua harness used its required child processes. Subsequent commands waited for resource admission when needed. Matched environments use SciMLBase 3.58.0, NonlinearSolve 4.32.0 and SymbolicIndexingInterface 0.3.55.Exact independent finding, unchanged analytic
[2, 3]assertions:Clean default: 6/6 pass. Unfixed parent: 0 pass, 6 fail, all three algorithms returning approximately
[3, 2], residual[-1, 1], andSuccess. Corrected source: 6/6 pass, approximately[2, 3]with near-zero original residuals.Same permanent test body against an exact archive of the unfixed parent and the corrected source:
Before, exit 1, no test errors:
After, exit 0:
The extracted assertion body matches the committed official test body exactly; source/archive and test-body hashes are recorded privately.
Independent view and analytic derivative controls, exit 0:
The derivative control is only
u=p²atp=2, with analytic derivative 4; it is not a general AD accuracy claim.Official groups, exit 0:
Core totals 69,612 passing assertions. Its existing autodiff fixture has zero assertions. The parent runtime reports
Threads.nthreads() = 4andBLAS.get_num_threads() = 1.Docs, formatting and spelling, exit 0:
The docs build completed document checks and HTML rendering; deployment was skipped outside CI. All three rendered algorithm contracts were inspected. Runic, typos and whitespace checks produced no failure. Algorithm docstring source is unchanged.
G1: analytic roots and independent residual/derivative controls. G2: all three algorithms, both original residual conventions, permutations and multidimensional/strided-view geometry. G3: alias checks, mutation isolation and repeated initialized solves. No assertions, tolerances, existing broken annotations or warning policies were weakened. No new dependency, version or prerequisite change.
Remaining gates
At intake, all 13 reported checks succeeded. The ancillary Dependabot Auto-merge run linked below has
startup_failure, zero check runs and no available failed-job log. No default-branch run exists for this pull-request workflow, so baseline equivalence is unverified; this source correction does not repair that workflow.The supplied fourth-round review contains independent executed findings but is not a counted merge rating because its intake exposed old labels. This author session supplies correction evidence only. H1 public-output/API compatibility and release/version policy remain unresolved; version 2.18.0 is unchanged. A fresh independent review is required; no reviewer was launched by this session.
Integration covers the prerequisite only through aabe095. Newer prerequisite revisions, their reset/getter contract and the combined stack remain unverified. Local LTS/prerelease/32-bit/downgrade matrices, downstream/GPU corpora and general derivative accuracy were not run. No release, registration, tag, merge, approval, closure or settings action. Remote CI completion after the correction is not claimed.
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 01a15cba-455f-7840-a71e-61b5d3b9fca9 (no session URL)