Skip to content

Fix method ambiguity in AbstractVectorOfArray similar() breaking QA on Julia 1.10 - #678

Draft
ChrisRackauckas-Claude wants to merge 4 commits into
SciML:masterfrom
ChrisRackauckas-Claude:fix/qa-similar-ambiguity-1.10
Draft

ChrisRackauckas-Claude wants to merge 4 commits into
SciML:masterfrom
ChrisRackauckas-Claude:fix/qa-similar-ambiguity-1.10

Conversation

@ChrisRackauckas-Claude

@ChrisRackauckas-Claude ChrisRackauckas-Claude commented Oct 8, 2026 •

Copy link
Copy Markdown
Member

🚧 UNREVIEWED — awaiting review by @ChrisRackauckas. Filed by an AI agent running as @ChrisRackauckas; Chris has not seen this.
Harness: Claude Code (orchestrator) with Codex CLI fixes and Grok Build and Codex reviews · Model: claude-opus-5-5, gpt-6.1-sol, grok-4.7
Conversation: https://claude.ai/code/session_01LPHREnnonfLg1VcE1EJovv

Problem

The package supports Julia 1.10 and later (julia = "1.10"). On Julia 1.10/1.11, similar(::AbstractVectorOfArray, ::Type, dims) throws a user-facing MethodError: ... is ambiguous when dims contains non-Int integers, such as (Int32(2), Int32(3)). Local Aqua QA on Julia 1.10 reports the ambiguity: master has 17 passed / 1 failed; the PR has 18/18 passed. The regression evidence below exercises the affected calls directly.

CI runs QA only on Julia 1 (latest stable). The shared SciML matrix script pins QA_VERSIONS = ["1"], overriding the repository's [QA] versions = ["lts", "1"]. The current PR checks contain only tests / QA (julia 1, ubuntu-latest) for QA. CI does not exercise this ambiguity on Julia 1.10/1.11; the evidence for those supported versions comes from local runs.

Root cause

Julia 1.10/1.11's Base defines three overlapping similar(::AbstractArray, ::Type, dims) fallbacks, including dims::Tuple{Integer, Vararg{Integer}} at abstractarray.jl:839. That particular fallback was removed in Julia 1.12 (methods(Base.similar, Tuple{AbstractArray,Type,Tuple}) only shows the NTuple{N,Int} and Tuple{Union{Integer,Base.OneTo},...} overloads there). RecursiveArrayTools defines similar(VA::AbstractVectorOfArray, ::Type{T}, dims::Tuple{Union{Integer,Base.OneTo}, Vararg{...}}), which is neither more nor less specific than Julia 1.10's Tuple{Integer, Vararg{Integer}} fallback once AbstractVectorOfArray <: AbstractArray (one dominates on the first argument, the other on the third) — hence the ambiguity, present only on Julia ≤ 1.11.

Bisect

  • Introduced: cde5c35 ("Make AbstractVectorOfArray <: AbstractArray for proper interface compliance", PR BREAKING: Make AbstractVectorOfArray <: AbstractArray #547, merged 2026-04-01). Before this, AbstractVectorOfArray was not an AbstractArray, so Base's similar fallbacks never entered the dispatch intersection.
  • Masked until: f3569c3 ("fix: resolve ArrayPartition ambiguity QA", PR fix: resolve ArrayPartition ambiguity QA #648, merged 2026-08-26) removed the blanket aqua_broken = (:ambiguities,) exemption. That PR's own verification fixed the copyto!/ldiv! ambiguities it found, but did not catch this one (version-dependent on Julia ≤ 1.11).
  • Confirmed via git log -L 1157,1166:src/vector_of_array.jl, which traces the ambiguous method directly to cde5c35.

Fix

Adds similar(VA::AbstractVectorOfArray, ::Type{T}, dims::Tuple{Integer, Vararg{Integer}}), exactly the "possible fix" Aqua's own diagnostic suggests, pinning the Integer-only intersection so it dominates both the existing RAT method and Base's 1.10/1.11 fallback. This mirrors the same two-method split Base itself already uses (NTuple{N,Int} + Tuple{Integer,Vararg{Integer}}), so it does not introduce a new ambiguity. No Aqua exclusion used.

Persistent regression coverage

test/Core/similar_tests.jl covers VectorOfArray and DiffEqArray, with Int32, UInt8, BigInt, and Bool tuple dimensions, and the existing Int, empty tuple, OneTo, and mixed Int/OneTo paths. Each successful call must return an Array with the expected size and Float64 element type.

The same committed test was run with master source from 76bec79, then with the PR's dispatch fix restored. No other source was changed.

Julia 1.10.12, without the dispatch fix (exit 1):

MethodError: similar(::VectorOfArray{Int64, 2, Vector{Vector{Int64}}}, ::Type{Float64}, ::Tuple{Int32, Int32}) is ambiguous.
Test Summary:                                  | Pass  Error  Total  Time
similar with explicit dimensions               |   24      8     32  4.1s

The eight errors are the four non-Int cases on each array type; the 24 assertions for existing paths pass.

Julia 1.10.12, with the dispatch fix (exit 0):

Test Summary:                    | Pass  Total  Time
similar with explicit dimensions |   48     48  0.3s

Julia 1.12.7, without and with the dispatch fix (both exit 0):

Test Summary:                    | Pass  Total  Time
similar with explicit dimensions |   48     48  2.6s
Test Summary:                    | Pass  Total  Time
similar with explicit dimensions |   48     48  3.5s

The regression commands were timeout 3600 julia +1.10 --compiled-modules=no --project=. -e 'include("test/Core/similar_tests.jl")' and timeout 3600 julia +1.12 --compiled-modules=no --project=.codex-validation-112 -e 'include("test/Core/similar_tests.jl")'. The Julia 1.12 project was an isolated local environment developing this checkout.

GROUP=Core timeout 3600 julia +1.10 --compiled-modules=no --project=.codex-validation-110 -e 'include("test/runtests.jl")' ran the official Core dispatcher using a local environment containing the package dependencies, test extras/targets and their compat constraints: 1,309 passed, 2 existing broken, no failures. The new testset appears as:

Test Summary:          | Pass  Total  Time
VecOfArr Similar Tests |   48     48  0.7s

Runic on test/Core/similar_tests.jl, test/runtests.jl, and src/vector_of_array.jl passed (exit 0), using timeout 3600 julia +1.10 --compiled-modules=no --project=$HOME/sandbox/goals/performance/runic-env -e 'using Runic; exit(Runic.main(ARGS))' -- --check <files>. typos on the same files and git diff --cached --check also passed (exit 0).

QA on Julia 1.10 is master 17 passed / 1 failed (the ambiguity), PR 18/18 passed. A fresh run at 1936cc26066359bfe5378b538e1c14e837240f72 completed successfully using the official dispatcher and an isolated local runner environment containing the package dependencies and test extras/targets:

GROUP=QA timeout 3600 julia +1.10 --project=.codex-qa-runner -e 'include("test/runtests.jl")'
Test Summary: | Pass  Total   Time
QA            |   18     18  22.6s

The runner was retained on JULIA_LOAD_PATH while the dispatcher activated its isolated QA environment. A first resumed attempt with --compiled-modules=no completed with 17 passes and one Aqua persistent-task shutdown failure; the ambiguity check passed. After Pkg.precompile() completed in the local runner and QA environments, the normal compiled-module run above passed. No test assertion, skip configuration, or time limit changed. Julia 1.12+ allocation behavior is unchanged; the regression passes all 48 assertions both before and after the fix on 1.12.7.

No Julia 1.11 rerun, other test groups, or new CI run was verified in this follow-up.

This comment-only follow-up reran timeout 3600 "$HOME/.juliaup/bin/julia" +1.10 --compiled-modules=no --project=. -e 'println("Julia ", VERSION); include("test/Core/similar_tests.jl")': Julia 1.10.12, 48/48 passed. Runic 1.13.0 (--check on all three PR files), typos on those files, and git diff --check passed (exit 0). Full Core, QA, and other groups were not rerun for this comment-only edit; the results above are from the prior head.

Risk assessment

  • Risk: medium, retaining the higher independent reviewer rating (M1).
  • Blast radius: the existing explicit-dimension similar dispatch fix for AbstractVectorOfArray; this follow-up only shortens an explanatory comment and corrects the PR description.
  • Evidence: the regression fails with eight ambiguity errors before the fix and passes 48 assertions afterward on Julia 1.10; Julia 1.12 passes all 48 both ways; Core passes 1,309 assertions with two existing broken assertions. Fresh Julia 1.10 QA passes 18/18 after local precompilation; the earlier shutdown-check failure is disclosed above.
  • Independent review: Grok Build grok-4.7 rated a999997 low; Codex gpt-6.1-sol and Devin SWE-2 rated 1936cc2 medium. The requested description/comment corrections are applied; the updated head has not been independently reviewed.
  • Merge: needs human review; independent re-review of the updated head remains pending.

Original implementation: Claude Code, model unknown, session https://claude.ai/code/session_01LPHREnnonfLg1VcE1EJovv

🤖 Review fixes written by Codex CLI 0.163.0 (model: gpt-6.1-sol); local session (transcript kept by the fleet master).

Risk assessment (independent review, Grok Build grok-4.7, reviewed head a999997)

  • Risk: low

  • Blast radius: One new Base.similar method on AbstractVectorOfArray for dims::Tuple{Integer,Vararg{Integer}}. It is the method Julia 1.10 and 1.11 define on AbstractArray and that Julia 1.12+ removed. Callers that already resolved similar keep the same result. Callers that threw MethodError: ambiguous on 1.10/1.11 (Int32, BigInt, and other non-Int integer dims) now get an Array. No public name is removed or renamed. Project.toml stays at 4.5.4. No new dependency.

  • Evidence: Head a999997421765c13e9fcd7d71280c03c171db6fc, rechecked unchanged at the end of the review. Diff is src/vector_of_array.jl only (+10). https://github.com/SciML/RecursiveArrayTools.jl/pull/678/files

    Julia 1.10.12, master 76bec79, detect_ambiguities(RecursiveArrayTools, Base) reported 1 ambiguity, the similar pair at vector_of_array.jl:1157 versus Base abstractarray.jl:839. similar(va, Float64, (Int32(2), Int32(3))) and the same call with BigInt dims threw that MethodError. Int, varargs, OneTo, mixed Int/OneTo, and the empty tuple already returned Array{Float64}.

    Julia 1.10.12, this head: those Int32 and BigInt calls return Matrix{Float64} of size (2, 3). detect_ambiguities against Base is 0. No new ambiguity.

    Julia 1.13.0, master and this head: the same calls all succeed, including Int32 and BigInt, and detect_ambiguities against Base is 0 both ways. The new method is dominated on 1.13 and does not change those results.

    CI at review time: 22/22 pending, no failed job to compare with master. Package tests: https://github.com/SciML/RecursiveArrayTools.jl/actions/runs/38868735951 . Runic: https://github.com/SciML/RecursiveArrayTools.jl/actions/runs/38868735327 . Downstream (includes SciMLSensitivity Core4): https://github.com/SciML/RecursiveArrayTools.jl/actions/runs/38868735487 . Master's latest run https://github.com/SciML/RecursiveArrayTools.jl/actions/runs/38819764786 failed only SciMLSensitivity.jl/Core4; a matching failure here would be pre-existing. Full GROUP=QA was not run; the check this PR exists to clear is detect_ambiguities, which was run. Local runic is a different CLI and was not used.

    No @test_broken, skipped test, loosened tolerance, allow-failure job, removed coverage, or new dependency.

  • Independent review: Grok Build grok-4.7 rated it low, high confidence: the 1.10 ambiguity reproduces and this method removes it without adding another.

  • Merge: auto-merge candidate — hold until the 22 pending checks are green. The change is a dispatch bugfix, not a public-API break, and it needs no version bump.


🤖 Posted by an AI agent — harness: Grok Build · model: grok-4.7 (independent reviewer; appended by Claude Code 2.1.301 · claude-opus-5-5)
Conversation: https://claude.ai/code/session_01VZjwf7Ux9YtTzwHGHMqnsq

🤖 Automated comment from an AI agent running as @ChrisRackauckas — not written or reviewed by Chris.

Risk assessment (independent review, Codex gpt-6.1-sol, head a999997)

  • Verdict: CHANGES
  • Rating: Codex gpt-6.1-sol rated it medium (M1) at head a999997
  • Risk: medium (M1: adds a new method on another package's function, Base.similar, changing dispatch for existing non-Int dimension calls; this is the highest matched criterion, above the otherwise applicable L6 error-to-success fix).
  • Blast radius: Explicit-dimension allocation through similar(::AbstractVectorOfArray, ::Type, dims), including VectorOfArray and DiffEqArray, particularly non-Int integer tuples on supported Julia 1.10/1.11. This is a peripheral allocation overload; the diff does not change the main indexing or broadcasting implementations. Existing Int tuples retain their more-specific method, and tested OneTo paths retain their allocation contract. No dependency, export, or new public name is added; no breaking API change or major-version bump is indicated.
  • Evidence: Read the full ten-line diff using git diff origin/HEAD...HEAD; reviewed the PR body/comments and linked history. There is no linked issue (closingIssuesReferences is empty). Extracted origin/HEAD and HEAD into scratch copies with git archive, leaving the checkout unchanged. Ran bash scratch/run-checks.sh, which sequentially executes timeout 3600 <local path> +<version> with the requested depot and JULIA_NUM_THREADS=4. The same scratch/probe.jl produced eight ambiguity errors on base on both 1.10.12 and 1.11.9; head passed 16 non-Int dimension assertions and 10 existing-path assertions on each. On 1.12.7 both base and head passed all 26 assertions. Ambiguity counts were base/head = 1/0 on 1.10 and 1.11, and 0/0 on 1.12. The probe covers VectorOfArray, DiffEqArray, Int32, UInt8, BigInt, Bool, ordinary Int, empty dimensions, and OneTo dimensions.
    Local QA used timeout 3600 <local path> +1.10 scratch/run-qa.jl scratch/<base|head> to execute each copy's unchanged test/QA/qa.jl: base rerun 17 passed, 1 failed (the ambiguity), head 18/18 passed. The first base QA attempt also failed Aqua's persistent-task shutdown check; that failure did not recur in the identical rerun, without changing its timeout or assertions. The final Core command was timeout 3600 <local path> +1.10 --project=scratch/head scratch/run-core.jl scratch/head; the setup script activates the scratch copy, installs its test dependencies, sets GROUP=Core, and includes the existing test/runtests.jl. Result: 1,261 passed, 2 pre-existing broken, no failures, including 150 interface assertions. Initial Core dependency setup failed on a cross-version scratch manifest; regenerating that manifest allowed the full run to complete.
    Read PR CI logs: GPU testsets passed 13/13, 10/10, 4/4; LTS AD testsets passed 22/22 adjoint, 8/8 Mooncake. Compared the failing PR Core4 log with the default-branch Core4 log: both used Julia 1.13.2 and downstream SciMLSensitivity SHA a0f7d2f571ece0da3dd7b2d5bd28d47c221684a1, and both failed EnsembleThreads at ensembles.jl:19 with AssertionError: mi2 !== nothing, reporting 15 passed, 1 error, 2 broken. Thus this observed CI failure also occurs on the default branch.
    G1: not applicable — no numerical algorithm, tolerance, or computed result changes. G2: pass — the changed overload was exercised locally, and PR GPU/AD logs confirm those suites actually executed; no Reactant or MPI path is changed. G3: not applicable — no shared state, cache, threading, or global default changes. No skipped/loosened tests or new copyleft dependency appears in the diff; the new code accesses public Base APIs.
  • Merge: needs changes (add a persistent Core regression test and correct the QA/LTS claim). Under M1, merge also requires Chris's decision after those 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.

🤖 Automated comment from an AI agent running as @ChrisRackauckas — not written or reviewed by Chris.

Risk assessment (independent review, Codex gpt-6.1-sol, head 1936cc2)

  • Verdict: CHANGES (PR-body attribution only; no code or test blocker)
  • Rating: Codex gpt-6.1-sol rated it medium (M1) at head 1936cc2
  • Risk: medium (M1: a new method on Base.similar changes dispatch for existing non-Int dimension calls).
  • Blast radius: explicit-dimension allocation through similar(::AbstractVectorOfArray, ::Type, dims); peripheral allocation, not indexing or broadcasting.
  • Evidence: Julia 1.10.12, committed test/Core/similar_tests.jl: head 48/48 pass; base 24 pass with 8 ambiguity errors. Julia 1.12.7: 48/48 on both. detect_ambiguities(RecursiveArrayTools, Base) on 1.10: base 1, head 0; 16 extra probe assertions pass. GROUP=Core on 1.10: 1,309 passed, 2 pre-existing broken, 0 failures. GROUP=QA on 1.10: 18/18. typos and git diff --check clean. The downstream SciMLSensitivity Core4 failure (AssertionError: mi2 !== nothing, ensembles.jl:19) also fails on current master, so it is pre-existing.
  • Findings: blocking: the body lacked the unreviewed banner and named a local transcript path and host (fixed in this body edit). Non-blocking: the five comment lines at src/vector_of_array.jl:1165–1169 narrate history ("removed upstream in 1.12"); describe the dispatch intersection in the present tense.
  • Merge: needs Chris (M1, medium).

🤖 Posted by an AI agent — harness: Codex CLI 0.162.1 · model: gpt-6.1-sol (independent reviewer; appended by Claude Code 2.1.302 · claude-opus-5-5)
Conversation: https://claude.ai/code/session_0133iSjsLBByPU93BDEQkNDF (fleet master); the review ran as a local headless Codex session with no public URL.

🤖 Automated review section from an AI agent running as Chris Rackauckas's account — not written or reviewed by Chris.

Independent executed findings at head a781d44 — session 01a15e28-f639-73a3-ba1f-86c591f4d8ef

The Base.similar dispatch fix has independent regression and official Core/QA evidence, but two commits still lack actual author session identifiers; medium/M1 remains Chris’s decision.

No introduced code/test blocker found. Recover real original author UUIDs, preserve signed/human history and existing higherM1, no use of reviewer UUID as author. Prior ratings leaked intake, findings-only. No local GPU/AD/downstream rerun, completeEverything or causal shutdown-flake claim; no merge before provenance and Chris’s M1decision.

Risk assessment

  • Risk: medium (M1).
  • Blast radius: The Base.similar dispatch fix has independent regression and official Core/QA evidence, but two commits still lack actual author session identifiers; medium/M1 remains Chris’s decision.
  • Evidence: Julia1.10/1.11 cleanbase24pass8ambiguityerrors→head48/48;1.12 both48/48. Additional39assertions perhead, zero head ambiguity, official Core1309pass2existingbroken and QA18/18. BaseQA repeat17pass1ambiguityfail after an unreproduced shutdown failure. Actual AD22/Mooncake8 and GPU13+10+4 pass; Core4Enzyme failure matches actual master log.
  • Independent review: Codex CLI0.163.0 (gpt-6.1-sol), local session 01a15e28-f639-73a3-ba1f-86c591f4d8ef (no session URL), reports CHANGES/medium (M1) at head a781d44. Findings-only, not counted toward merging because historical rating text appeared in the supplied intake.
  • Merge: Held on the concrete findings above. Higher existing assessments and the parent stack or human/API/provenance decisions remain controlling; no approval, merge, closure, settings or release action is authorized by this review.

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)

🤖 Automated review section from an AI agent running as Chris Rackauckas's account — not written or reviewed by Chris.

Risk assessment (independent review, Codex CLI (gpt-6.1-sol), local job oss-reviews-2026-10-22-SciML-RecursiveArrayTools-jl-678-a781d44 (no session URL), head a781d44)

  • Verdict: CHANGES
  • Risk: medium (M1)
  • Summary: The dispatch fix and regression tests are correct, but the supplied snapshot retains an unresolved CHANGES verdict on this exact head, which fails the requested merge gate.
  • Merge: needs changes — fix the review findings below

Executed review notes (head a781d44):

Findings

  1. pr.json:1 (body, “Independent executed findings at head a781d44”) — blocking, review-policy gate. The snapshot explicitly records CHANGES/medium (M1) at a781d44e25c93d2be2b7b9c93b8fd6c5e1679925, with an outstanding provenance concern and no subsequent clearance. The requested <local path> requires “no open CHANGES verdict on the current head” and says a failed gate requires CHANGES. Obtain an explicit resolution of that existing review; medium/M1 also requires Chris's decision under that policy. This is the sole reason for this verdict: I found no introduced source or test defect. I have not independently substantiated the previous provenance allegation and do not request a history rewrite or additional code changes.

Evidence

Reviewed head a781d44e25c93d2be2b7b9c93b8fd6c5e1679925 against merge base 76bec79f7a09ce9546709376a0d7eb95deaf90f9. All execution used copies under tmp; test commands set JULIA_NUM_THREADS=4, use an explicit scratch --project, and have timeout 2400 limits.

Risk criteria matched:

  • L2: adds substantive regression assertions and wires them into Core; no existing assertion, tolerance, test group, or CI job is removed or weakened.
  • L6, in substance: fixes erroneous ambiguity failures on Julia 1.10/1.11, with the committed test failing before and passing afterward; existing allocation contracts remain equal in the tested cases.
  • M1, controlling: adds a method on another package's function (Base.similar) and changes existing dispatch. Highest matched level: medium. This affects peripheral explicit-dimension allocation for AbstractVectorOfArray, including VectorOfArray and DiffEqArray; it does not modify the main indexing or broadcasting implementations.

Before opening pr.json, I recorded a provisional low/L6 assessment and L2 in tmp/risk-before-body.txt. The final assessment corrects that provisional omission of the rubric's explicit M1 rule; it also preserves the existing higher rating as the rubric requires. This is not a claim that medium/M1 was my initial blind rating.

The implementation at src/vector_of_array.jl:1166 defines the exact intersection of the existing package overload and Base's integer-tuple fallback. The existing all-Int overload remains more specific, including for the empty tuple. The new method forwards to the same similar(Array{T}, dims) allocation used by the broader package overload. No exports, documented return types, supported versions, dependencies, or licenses change; no breaking SemVer change is indicated.

The committed regression test uses independently specified sizes and element types, not uninitialized array values or results copied from the implementation. It covers both affected concrete types, four non-Int integer types, ordinary Int, empty dimensions, OneTo, and mixed integer/range dimensions. Its real failures on the base establish that it can catch removal of the fix.

Commands and observed output:

cat <local path>
cat pr.diff
git -C repo rev-parse HEAD
git -C repo merge-base HEAD origin/master
git -C repo archive HEAD | tar -x -C tmp/head
git -C repo archive 76bec79f7a09ce9546709376a0d7eb95deaf90f9 | tar -x -C tmp/base
bash tmp/run110.sh
bash tmp/run111.sh
bash tmp/run112.sh

The scripts run tmp/probe.jl against each source copy. That probe includes the unchanged committed test/Core/similar_tests.jl from the head. Each invocation uses --startup-file=no --compiled-modules=no --project=<scratch-copy>. Retained logs and scripts are in tmp.

Julia Source Committed regression Package ambiguity count Existing-contract assertions
1.10.12 base 24 pass, 8 errors; exit 1 1 90 pass
1.10.12 head 48 pass; exit 0 0 90 pass
1.11.9 base 24 pass, 8 errors; exit 1 1 90 pass
1.11.9 head 48 pass; exit 0 0 90 pass
1.12.7 base 48 pass; exit 0 0 90 pass
1.12.7 head 48 pass; exit 0 0 90 pass

Representative actual base error:

MethodError: similar(::VectorOfArray{Int64, 2, Vector{Vector{Int64}}}, ::Type{Float64}, ::Tuple{Int32, Int32}) is ambiguous.

Actual head output on Julia 1.11.9:

RAT ambiguities: 0
existing allocation contract |   90     90  1.0s
additional integer dimensions and forwarding |   75     75  0.8s
similar with explicit dimensions |   48     48  0.4s

The additional 75 assertions also pass on head 1.10 and on both sources on 1.12. They cover singleton and heterogeneous integer dimensions, a 3-D VectorOfArray, zero dimensions, negative dimensions, different element types, and tuple/vararg forwarding. Existing-contract checks cover exact result types, sizes, source preservation, Int and range dimensions, and two-argument forwarding. No numerical algorithm changes; G1 is inapplicable. No cache, threading, shared-state, or global-default change; G3 is inapplicable.

Local test environment setup: tmp/setup-runner110.jl builds a separate runner from the package's declared dependencies and test target, developing both the head and its local shorthand sublibrary. KernelAbstractions is constrained to the supported 0.9.36 compat series. Two preliminary scratch setup attempts failed (compat-string parsing, then a missing GPUCompiler manifest entry); rebuilding the separate runner succeeded. These are recorded in tmp/setup-core110.log, tmp/setup-core110-fixed.log, and tmp/setup-runner110.log.

export JULIA_DEPOT_PATH="$PWD<local path>
export JULIA_NUM_THREADS=4 JULIA_PKG_PRECOMPILE_AUTO=0 TMPDIR="$PWD/tmp"
GROUP=Core timeout 2400 tmp/julia-1.10.12/bin/julia \
  --startup-file=no --compiled-modules=no --project=tmp/runner110 \
  -e 'include("tmp/head110/test/runtests.jl")'
timeout 2400 tmp/julia-1.10.12/bin/julia \
  --startup-file=no --compiled-modules=no --project=tmp/runner110 \
  -e 'include("tmp/head110/test/QA/qa.jl")'

Core exit 0: 1,309 passed, 2 existing broken, 0 failures/errors. The full official Core dispatcher executed, including:

VecOfArr Indexing Tests |  180       2    182  15.4s
VecOfArr Interface Tests |  150    150  23.5s
VecOfArr Similar Tests |   48     48  0.5s

The counts above are summed from all 13 testset summaries in tmp/core110.log; the two broken assertions are in the unchanged indexing tests.

QA exit 0, from the unchanged official QA file, with output in tmp/qa110.log:

Test Summary:     | Pass  Total     Time
Quality Assurance |   18     18  1m39.8s

Read-only CI verification:

gh run view 39095052285 --repo SciML/RecursiveArrayTools.jl --job 117579651639 --log
gh run view 38819764786 --repo SciML/RecursiveArrayTools.jl --job 116713203524 --log
gh run view 39095052556 --repo SciML/RecursiveArrayTools.jl --job 117579699531 --log
gh run view 39095052556 --repo SciML/RecursiveArrayTools.jl --job 117579699354 --log
gh run view 39095052556 --repo SciML/RecursiveArrayTools.jl --job 117579699378 --log
gh run view 39095052556 --repo SciML/RecursiveArrayTools.jl --job 117579699427 --log

The supplied rollup has 41 SUCCESS, 1 FAILURE, 4 SKIPPED. The failed SciMLSensitivity Core4 job and the merge-base master job both show Julia 1.13.2, EnsembleThreads at ensembles.jl:19, AssertionError: mi2 !== nothing from Enzyme, and 15 pass, 1 error, 2 broken. Thus the observed failure also exists without this patch. Full logs are retained as tmp/pr-core4.log and tmp/base-core4.log; CI is not entirely green.

Actual PR CI logs confirm Core ran the new test on Julia 1.10.12, with VecOfArr Similar Tests | 48 48. QA ran on Julia 1.13.2, with 20/20. GPU testsets actually ran and passed 13/13, 10/10, 4/4; LTS AD testsets passed 22/22 and 8/8 Mooncake, satisfying G2's exercise requirement for the related suites. No AD rule or GPU kernel is changed by this diff.

The PR's corrected QA matrix claim agrees with both its actual CI jobs and the fetched shared script (compute_affected_sublibraries.jl@v1, QA_VERSIONS = ["1"], retained under tmp). The historical introduction and ambiguity-exclusion removal agree with git log -L and git show f3569c3 -- test/QA/qa.jl. I confirmed the Base fallback in Julia 1.11 source as well as reproducing it at runtime. The body's main correctness and regression claims hold in these runs.

git -c gc.auto=0 -C repo diff 76bec79 HEAD --check
git -c gc.auto=0 -C repo status --porcelain=v1

Both produced no output. The working tree remains unchanged. The three PR files in all tested head copies were byte-compared with the checkout and matched. No commit, push, GitHub review/comment, or source edit was made.

Not verified

  • Did not resolve or independently authenticate the previous review's author-session/provenance claim; did not obtain Chris's M1 decision or clear the current-head review gate.
  • Did not run the base's full QA suite or full Core locally; the before/after evidence is the committed regression plus independent probes. Full head Core and QA are reported above.
  • Did not locally rerun GPU, AD, Downstream, or IntegrationTest suites; inspected actual CI logs for the specific jobs above. Did not test Julia 1.13 locally, other operating systems, or 32-bit Julia.
  • Did not build the manual or independently rerun the PR author's formatter/typos tools; there is no manual change and the diff whitespace check passes.
  • Did not reproduce every historical run, exact former dependency environment, benchmark claim, or earlier QA shutdown failure described in the body. No performance gain is claimed by this patch.

🤖 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-22-SciML-RecursiveArrayTools-jl-678-a781d44 (no session URL)

🤖 Automated review section from an AI agent running as Chris Rackauckas's account — not written or reviewed by Chris.

Fix by Devin CLI 3000.11.228 swe-2-high (head a781d44)

Routed finding: the newest review's only blocker is a review-policy gate — an open CHANGES verdict on this head carrying a provenance concern ("two commits still lack actual author session identifiers"). That review reported no introduced source or test defect and requested no code changes.

Resolution. Commits 1936cc2 and a781d44 carry an Agent-Session trailer naming a transcript path and host instead of a session UUID — the trailer form dictated verbatim by the fixer job brief. Correcting pushed trailers would require rewriting the branch history, which is not permitted, so the recovered provenance is recorded here for audit. Both are real Codex CLI 0.163.0 (gpt-6.1-sol) rollouts on the authoring machine, matched by the git commit -F tool call and the resulting commit SHA inside each rollout log:

  • 1936cc2 (authored 2026-10-17T14:26:30-04:00): author session 01a14b0b-42fc-7fc2-b310-765aa5470a64; its commit tool call ran at 2026-10-17T18:26:30Z. Follow-on session 01a14b27-972c-73f1-a1d0-c77aa92884c9 only reran GROUP=QA and pushed — no commit invocation.
  • a781d44 (authored 2026-10-17T23:50:51-04:00): author session 01a14d20-1154-71c2-82b8-eabbf2196a0a; its commit tool call ran at 2026-10-18T03:50:49Z.

These are the authors' own session identifiers, not reviewer session identifiers. Runnable probe: git log --format='%(trailers:key=Agent-Session,valueonly)' -1 <sha> prints each trailer; grep -l <full-sha> over the harness's session rollout logs then matches each commit to its authoring session, and the rollout's session_meta line carries the UUIDs above.

No code changes. Head remains a781d44: the routed review found no source or test defect, the public surface stays minimal (one added Base.similar method), and no test was skipped, loosened or deleted. The medium/M1 merge sign-off remains Chris's decision per the review policy; nothing here approves, merges, or clears that gate.

Fail-before / pass-after re-demonstrated with the committed test/Core/similar_tests.jl, Julia 1.10.12 and 1.11.9, merge-base 76bec79 vs head:

  • 1.10 base: 24 passed, 8 errored (exit 1) — MethodError: similar(::VectorOfArray{Int64,2,Vector{Vector{Int64}}}, ::Type{Float64}, ::Tuple{Int32,Int32}) is ambiguous.
  • 1.10 head: similar with explicit dimensions | 48 48 (exit 0)
  • 1.11 base: 24 passed, 8 errored (exit 1); 1.11 head: 48 48 (exit 0)

Validation run against a git archive extraction of the head (runner environment dev'ing the extraction, JULIA_NUM_THREADS=4):

GROUP=Core julia +1.10 --project=<runner-env> -e 'include("test/runtests.jl")'
# 13 testsets pass; "VecOfArr Similar Tests | 48 48 0.4s"; the only broken
# assertions are the 2 pre-existing ones in "VecOfArr Indexing Tests".

GROUP=QA julia +1.10 --project=<runner-env> -e 'include("test/runtests.jl")'
# QA | 18 18 16.8s

julia +1.12 --project=@runic -m Runic --check src/vector_of_array.jl test/Core/similar_tests.jl test/runtests.jl   # exit 0
typos <PR diff and the three changed files>                                                                   # exit 0

Pre-existing CI red: the only failing check, the SciMLSensitivity.jl/Core4 downstream job, fails identically on the latest default-branch CI run (AssertionError: mi2 !== nothing at ensembles.jl:19, an Enzyme/SciMLSensitivity failure unrelated to this diff).

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: Devin CLI 3000.11.228 · model: swe-2-high
Conversation: local fixer job SciML__RecursiveArrayTools.jl__678 (no session URL)

…) on Julia 1.10

Making AbstractVectorOfArray <: AbstractArray (SciML#547) made RAT's
similar(VA::AbstractVectorOfArray, ::Type{T}, dims::Tuple{Union{Integer,Base.OneTo},
Vararg{...}}) ambiguous with Base.similar(a::AbstractArray, ::Type{T},
dims::Tuple{Integer, Vararg{Integer}}), a Base fallback method that exists on
Julia 1.10/1.11 but was removed in 1.12. This was masked by the Aqua
ambiguities exemption until SciML#648 removed it, so GROUP=QA on Julia 1.10 (the
"lts" CI matrix entry) started failing on master. Adds the more specific
Integer-only method Aqua's own diagnostic suggested, mirroring the analogous
pair of methods Base itself defines, resolving the ambiguity without an Aqua
exclusion.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Agent-Harness: Claude Code
Agent-Model: claude-sonnet-5
Agent-Session: https://claude.ai/code/session_01LPHREnnonfLg1VcE1EJovv
@ChrisRackauckas

Copy link
Copy Markdown
Member

🤖 Automated comment from an AI agent running as @ChrisRackauckas — not written or reviewed by Chris.

Independent review (Devin CLI 3000.11.3, model fusion-claude-opus-5-5-high-sidekick-swe-2-medium): CHANGES, risk low.

Full review

VERDICT: CHANGES
RISK: low

The added method is correct. Running it confirms it removes the ambiguity on Julia 1.10 and 1.11. On 1.12 and 1.13 it is harmless: it returns the same results as master. Two problems remain. The PR adds no test that CI will actually run. The PR body also misdescribes what the bug is and where CI would catch it.

Blocking findings

  1. No regression test that CI runs. The bug is a user-facing MethodError, not just an Aqua complaint. (src/vector_of_array.jl:1170; no file under test/ changed)

    • Confirmed by running scratch/probe.jl on the merge base 02c477c. With Julia 1.10.12 and 1.11.9, every call to similar(::AbstractVectorOfArray, T, dims) whose dims are non-Int integers throws. Examples: similar(VA, Float32, (Int32(2), 3)), (UInt8(2),), (big(2), 2), (true, 2). The error is MethodError: similar(::VectorOfArray{...}, ::Type{Float32}, ::Tuple{Int32, Int64}) is ambiguous. It happens for VectorOfArray (both 2-D and 3-D) and for DiffEqArray.
    • With the PR applied, all of those calls return Matrix{Float32} / Vector{Float32} of the right size on 1.10, 1.11, 1.12 and 1.13. On 1.12 and 1.13 the output is identical to the merge base's.
    • The PR's only before/after evidence is the Aqua ambiguity check in GROUP=QA. CI never runs QA on lts. SciML/.github scripts/compute_affected_sublibraries.jl pins the QA group to QA_VERSIONS = ["1"] regardless of what test_groups.toml says. The PR's own CI matrix (run 37807101121, detect job) contains only {"group":"QA","version":"1"}, and "1" now resolves to 1.13, where the ambiguity cannot occur.
    • So nothing in CI would catch a regression of this fix.
    • Required change: add a Core test. Core does run on lts. Put it, for example, in test/Core/interface_tests.jl, looping over a few non-Int dims tuples, e.g. (Int32(2), 3), (UInt8(2),), (Int32(2), Int32(3)). For each, assert similar(testva, Float32, dims) isa Array{Float32} and that size equals Int.(dims). On the merge base this test fails on Julia 1.10 with the MethodError above. Paste that failure and the post-fix pass into the PR body, as CLAUDE.md requires for bug fixes.
  2. The PR body's central CI claim is false. (PR description, "Problem" section)

    • The body says "CI does run QA on Julia 1.10 … So this is a real CI break on master's lts QA lane". Confirmed by reading the CI matrix and the central script cited above: there is no QA lane on lts. On master, the QA lane runs on Julia "1" and passed (master CI run 36260267778).
    • The real impact is the user-facing MethodError on Julia 1.10/1.11 described in finding 1. Julia 1.10 is supported (julia = "1.10" compat).
    • Required change: rewrite the Problem / Risk sections to describe the actual bug: ambiguous similar with non-Int dims on Julia ≤ 1.11. Drop the CI-break claim. The "Merge: auto-merge candidate" rationale rests on that claim and should be reworded too.

Non-blocking findings

  • The comment is too long. (src/vector_of_array.jl:1165-1169) Five of the ten added lines are comments, well above the <10% guideline in CLAUDE.md. The phrase "removed upstream in 1.12" is version-history narration. One line is enough, e.g. # Disambiguates against Base's Tuple{Integer,Vararg{Integer}} fallback on Julia ≤ 1.11.
  • The Base claim checks out. Confirmed by running methods(similar, Tuple{AbstractArray,Type,Tuple}): 1.10.12 and 1.11.9 have the Tuple{Integer, Vararg{Integer}} fallback; 1.12.7 and 1.13.0 do not. 1.13 adds a Tuple{Union{Integer,Base.AbstractOneTo},...} fallback, and RAT's existing Union{Integer,Base.OneTo} method is strictly more specific than it, so 1.13 shows no new ambiguity.
  • The new method adds no ambiguity of its own. Confirmed by running Test.detect_ambiguities(RecursiveArrayTools; recursive=true), filtered to RAT methods. It finds 1 ambiguity on base with 1.10/1.11, and 0 with the PR on 1.10, 1.11, 1.12 and 1.13. Dispatch also checks out: Tuple{Int,Int} still goes to the Tuple{Vararg{Int}} method, and Tuple{Int32,Int32} goes to the new method.
  • Possible textual conflict with sibling PR fill!(::AbstractVectorOfArray, x): fill inner arrays directly, fixing a silent ragged bug #669. Its hunk starts at @@ -1167 in src/vector_of_array.jl, immediately after this PR's insertion point. Suspected from reading the hunk headers; I did not attempt a merge. No interface overlap with the other open RAT PRs (668, 671, 673 touch other regions).
  • The bisect story is consistent with history, checked by reading only. cde5c35 adds abstract type AbstractVectorOfArray{T, N, A} <: AbstractArray{T, N}, and f3569c3 deletes aqua_broken = (:ambiguities,) from the test config. I did not run QA at historical commits.
  • No new dependencies, exports or public API. There is no linked issue or tracking issue.

What I ran

All runs used TMPDIR set under the review directory. The merge base was extracted with git archive 02c477c into scratch/base, and the PR head with git archive HEAD into scratch/prcopy. Nothing was written inside repo/; git status there is clean.

  • scratch/probe.jl on Julia 1.10.12, 1.11.9, 1.12.7 and 1.13.0, against both base and PR (logs in scratch/probe-{base,pr}-<ver>.log). It covers the Base fallback list, ambiguity detection, similar(A, Float32, dims) for VectorOfArray (2-D and 3-D) and DiffEqArray over 9 dims shapes, which dispatch, and the 2-argument similar(VA, dims). Results:
    • base on 1.10/1.11: 6 of 9 shapes throw an ambiguity MethodError for each type.
    • PR on all four versions: every shape returns a correctly sized Array.
    • On 1.11 the base probe stopped at the which(...) line with the same ambiguity error, after printing the same per-shape results as on 1.10.
  • GROUP=QA julia +1.10 --project -e 'using Pkg; Pkg.test()'
    • base: Quality Assurance | 17 pass, 1 fail. The single ambiguity is exactly the one the PR quotes, and Aqua suggests the same "possible fix".
    • PR: QA | 18 pass, 18 total. This reproduces the PR's before/after.
  • Runic (julia +1.12 --project=@runic -m Runic --check --diff src/vector_of_array.jl on the PR copy): clean. typos over the diff: clean.
  • Read the PR's CI checks for head fc807f2: Core lts, 1, pre and x86, Downstream and SII all pass. The SciMLSensitivity Core1 downstream job fails; I did not investigate it, and it is unrelated to similar. I also read the CI detect matrix and the central QA clamping in SciML/.github scripts/compute_affected_sublibraries.jl@v1.

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
Conversation: local Claude session 3c311569-dda6-4687-bc9f-65febb212c33 (fleet master)

ChrisRackauckas and others added 3 commits October 16, 2026 07:40
Cover non-Int integer tuples and existing Int, empty and OneTo paths for
VectorOfArray and DiffEqArray. The new test reports eight ambiguity errors
without the dispatch fix on Julia 1.10 and passes 48 assertions with it;
Julia 1.12 passes the same assertions before and after.

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, transcript /home/crackauc/sandbox/goals/performance/jobs/rat/qa-master/log-codex.txt on amdci2
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, transcript /home/crackauc/sandbox/goals/performance/jobs/rat/qa-master/log-codex.txt on amdci2

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants