Skip to content

Fix OUQBase 𝔼/ℙ SymbolicUtils Operator ambiguity (separate from #54 floor) - #59

Merged
ChrisRackauckas merged 9 commits into
SciML:mainfrom
ChrisRackauckas-Claude:agent/54-ouqbase-promote-symtype
Oct 3, 2026
Merged

ChrisRackauckas merged 9 commits into
SciML:mainfrom
ChrisRackauckas-Claude:agent/54-ouqbase-promote-symtype

Conversation

@ChrisRackauckas-Claude

@ChrisRackauckas-Claude ChrisRackauckas-Claude commented Sep 26, 2026 •

Copy link
Copy Markdown
Member

Summary

OUQBase Core fails on current SymbolicUtils (≥4.38, including latest 4.48) with MethodError: promote_symtype(::𝔼_, ::Type{Real}) is ambiguous against promote_symtype(::Operator, ::Type{T}). This is the same failure seen in Downgrade Sublibraries (CI run 35162761668) and Sublibrary CI Core. This PR resolves the ambiguity, switches Term construction to SymbolicUtils.term, and fixes follow-on group-lookup / raw-moment parsing that only become reachable once Operators construct successfully.

Independent review: Codex gpt-6-astra rounds 1-4 CHANGES (each fixed); Claude Code claude-opus-5-5 (a different harness from the Cursor author) round 5 on head 630a206: VERDICT MERGE, no blocking findings. Codex is out of quota until 2026-10-03, so round 5 used Opus.

Round-2 follow-up on this branch: get_raw_moment_order now checks isinteger before Int(...) so non-integer exponents raise the descriptive raw-moment error instead of InexactError.

Verification

Non-integer raw-moment exponent (round-2 finding)

Before:

BEFORE_ERR_TYPE=InexactError
BEFORE_ERR=InexactError: Int64(2.5)
Test Summary:                               | Fail  Total  Time
non-integer exponent before isinteger guard |    2      2  4.0s

After:

Test Summary:                                        | Pass  Total   Time
OUQBase operator regressions (after isinteger guard) |   16     16  45.8s

Probability ≳/≲ regression (round-1 finding)

Before (pre-Inequality unwrap): 10 pass, 2 fail, 2 error (Any[] / AssertionError).
After: 14/14 (then 16/16 with the isinteger assertion).

OUQBase Core (TEST_GROUP=Core, julia +lts)

promote_symtype operators | 14/14 (now 16/16 with extra assertions)
Flood Problem (Q only) | completes
Flood Problem (canonical moments objective) | 1 error: isapprox(::BasicSymbolic, ::Float64)

OUQBase QA (TEST_GROUP=QA)

Quality Assurance 16/16 on julia +lts (prior head); reviewer also saw 18/18 on +release.

Out of scope: canonical-moments objective_f / symbolic isless

Not fixed in this PR (and no upstream issue filed here). Standalone Symbolics-only reproducer + version bisect live in the job REPORT.md:

  • Current Symbolics 7.41.1 / SymbolicUtils 4.48.0: evaluate(H, d) is numeric; evaluate(substitute(H ≳ h, …), d) leaves isless(2.0, (1000.0 / (9000.0sqrt(0.0009)))^0.6) unfolded.
  • Symbolics 6.58.0 folds the same ≳ comparison to true::Bool; breakage begins at Symbolics 7.0.0.

What I did NOT verify

  • Full green OUQBase Core (blocked on upstream evaluate/isless for ≳).
  • Root-package Downgrade workflow end-to-end.
  • Whether dropping the getdefault via-owners ignore (reviewer finding 3) is safe on every CI Julia lane.

Reviewer pushback

Part of #54

Please ignore this draft until reviewed by @ChrisRackauckas.

Risk assessment

  • Risk: medium
  • Blast radius: OUQBase Operator construction (𝔼/ℙ), RV group resolution, raw-moment parsing (including non-integer exponent errors).
  • Evidence: fail-before/pass-after for promote_symtype, ≳ discovery, and non-integer moment order; QA green locally; Core still blocked only on disclosed Symbolics isless.
  • Independent review: Codex gpt-6-astra round 1 CHANGES (fixed); Claude Code Opus 5.5 round 2 on 5242c31 MERGE.
  • Merge: approved by round-2 independent review; wait for @ChrisRackauckas.

Harness: Cursor Agent CLI 2026.09.26-dd393fe; model: auto; transcript: /home/crackauc/sandbox/agent-jobs/OptimalUncertaintyQuantification.jl/jobs/54-cursor/log.txt on amdci2.julia.csail.mit.edu

Update (Codex gpt-6-astra round-4 CHANGES)

Removed the QA all_qualified_accesses_via_owners ignore for :getdefault and the comment that preserved the non-owner access. getdefault (and qualified getbounds) now go through their owner ModelingToolkitBase, declared as a direct dependency (compat = "1.50", matching ModelingToolkit 11.31).

Ownership fail-before / pass-after

Before (e09a134, no ignore):

OWNERSHIP_CHECK=FAIL
QualifiedAccessesFromNonOwnerException
getdefault has owner ModelingToolkitBase but it was accessed from ModelingToolkit
.../canonical_moments.jl:198:48

After (630a206, no ignore):

getdefault access sample: ModelingToolkitBase
OWNERSHIP_CHECK=PASS

Re-verification (OPTIMALUNCERTAINTYQUANTIFICATION_TEST_GROUP)

julia +lts (1.10.12):

promote_symtype operators |   25     25
Flood Problem (Q only) | completes
Flood Problem (canonical moments objective) | 1 error: isapprox(::BasicSymbolic, ::Float64)  [disclosed; fixed in #60]
Quality Assurance |   16     16
Testing OUQBase tests passed  (QA)

julia +1 (1.13.0):

promote_symtype operators |   25     25
Flood Problem (canonical moments objective) | 1 error [same disclosed]
Quality Assurance |   18     18
Testing OUQBase tests passed  (QA)

Harness: Cursor Agent CLI 2026.09.26-dd393fe; model: auto; transcript: /home/crackauc/sandbox/agent-jobs/OUQ-b/jobs/54-cursor/log.txt on amdci2.julia.csail.mit.edu

Risk assessment

  • Risk: medium
  • Blast radius: Only the OUQBase sublibrary. Affected: 𝔼/ℙ/𝟙 operator term construction (now built with SymbolicUtils.term, plus a new promote_symtype(::𝔼_/ℙ_, ::Type{T}) method), random-variable group lookup (get_ordered_group_names now goes through the new internal underlying_random_variables), raw-moment parsing (get_raw_moment_order rewritten; the RHS is now coerced with Float64(...)), and a new direct dependency on ModelingToolkitBase (compat 1.50, SciML, MIT). CanonicalMoments, DiscreteMeasures and the umbrella source are untouched. Draft PR OUQBase: evaluate Inequality probability events as Bool comparisons #60 edits the same 9 files, and PR Fix QA: explicit imports, OUQBase docs, approved reexports #57 edits qa.jl, interface.jl and operators.jl, so conflicts are certain.
  • Evidence: 5 checks fail on head 630a206. None is a regression:
    • tests / QA (julia 1): the same result on main 013f14a (run 35162761805): 18 pass, 2 fail, 1 error (no_implicit_imports, public-API docstrings, unapproved reexports). Pre-existing.
    • Downgrade Sublibraries / test (lib/DiscreteMeasures): the same 5 intersect ArgumentErrors on main (run 35162761668). Pre-existing, and this PR doesn't touch it.
    • Downgrade Sublibraries / test (lib/OUQBase): main fails earlier, at Flood Problem (Q only) with the promote_symtype(::𝔼_, ::Type{Real}) is ambiguous error. The PR gets past that and fails later at Flood Problem (canonical moments objective) with isapprox(::BasicSymbolic, ::Float64). Pre-existing red that the PR partly fixes.
    • sublibraries / lib/OUQBase / Julia 1 and / Julia lts / Tests - Core: these jobs are skipped on main pushes (path detection), so there is no main baseline. I compared against PR Fix QA: explicit imports, OUQBase docs, approved reexports #57 instead (run 36274860212, no fix), where both fail at Q only with the same ambiguity. With this PR they fail only at the isapprox error, which the description discloses as out of scope and handled in OUQBase: evaluate Inequality probability events as Bool comparisons #60. Pre-existing, improved.
    • Newly passing: lib/OUQBase [QA] / Julia 1 (PR Fix QA: explicit imports, OUQBase docs, approved reexports #57's run had 1 failure).
    • Everything else passes: Docs, Runic, typos, root Core lanes, Downgrade Core, benchmark.
  • Findings from the diff:
    • No tests were weakened. A new Core testset was added. The QA ignore list got stricter (:getdefault removed; access now goes through its owner ModelingToolkitBase, and the sublib QA check passes).
    • The QA ignore list is now stale, and the description doesn't mention it. :Term and :symtype stay in all_explicit_imports_are_public even though operators.jl no longer imports them. The comment still says the compat caps are "SymbolicUtils 3.x / ModelingToolkit 9.x", which doesn't match the current compat.
    • Operator is now imported from SymbolicUtils instead of Symbolics.
    • get_raw_moment_order now throws ErrorException for non-integer or non-power forms, where it used to hit a different path. The OUQBase version stays at 0.1.0 and the changed functions aren't exported, so this is a minor SemVer concern.
  • Description: The body contains two risk sections that contradict each other (an older "round-2 on 5242c31" block plus an update). It says Core is not fully green. It has no review comments on GitHub (0 review, 0 issue comments). It asks to be ignored until @ChrisRackauckas reviews it.
  • Independent review: Devin CLI (Mac) / fusion-claude-opus-5-5-high-sidekick-swe-2-medium rated it medium, high confidence: CI shows no regressions and it fixes the documented ambiguity, but OUQBase Core is still red, it adds a direct dependency, rewrites parsing logic, leaves QA ignores stale, and overlaps open PRs Fix QA: explicit imports, OUQBase docs, approved reexports #57 and OUQBase: evaluate Inequality probability events as Bool comparisons #60.
  • Merge: needs human review. Reasons:

🤖 Risk assessment posted by an AI agent (fleet master) — harness: Devin CLI (Mac) / fusion-claude-opus-5-5-high-sidekick-swe-2-medium; dispatched by Claude Code head, model claude-opus-5-5[1m]
Conversation: local Claude Code session 3cd6500a-1f81-46b5-ac0b-c466e15b6a53 on Chris's Mac (session ID, no URL)

ChrisRackauckas and others added 4 commits September 26, 2026 08:43
Add Type-specialized promote_symtype methods so SymbolicUtils Operator
dispatch is unambiguous, and build terms via SymbolicUtils.term so the
SymVariant Term API is used instead of Term{Real}.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Cursor Agent <noreply@cursor.com>
Agent-Harness: Cursor Agent CLI 2026.09.26-dd393fe
Agent-Model: auto
Agent-Session: local session, transcript at /home/crackauc/sandbox/agent-jobs/OptimalUncertaintyQuantification.jl/jobs/54-cursor/log.txt on amdci2.julia.csail.mit.edu
Symbolics treats Operator applications as variable leaves, so
get_variables(𝔼(Q^n)) returned 𝔼(Q^n) and group lookup failed. Unwrap
OUQ operators and collect variables from their arguments.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Cursor Agent <noreply@cursor.com>
Agent-Harness: Cursor Agent CLI 2026.09.26-dd393fe
Agent-Model: auto
Agent-Session: local session, transcript at /home/crackauc/sandbox/agent-jobs/OptimalUncertaintyQuantification.jl/jobs/54-cursor/log.txt on amdci2.julia.csail.mit.edu
Replace the broken @rule chain with TermInterface extraction, and unwrap
Const-wrapped numeric RHS values before filling Float64 moment sequences.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Cursor Agent <noreply@cursor.com>
Agent-Harness: Cursor Agent CLI 2026.09.26-dd393fe
Agent-Model: auto
Agent-Session: local session, transcript at /home/crackauc/sandbox/agent-jobs/OptimalUncertaintyQuantification.jl/jobs/54-cursor/log.txt on amdci2.julia.csail.mit.edu
Cover promote_symtype for 𝔼_/ℙ_, underlying RV extraction through 𝔼(Q^n),
and raw moment order parsing.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Cursor Agent <noreply@cursor.com>
Agent-Harness: Cursor Agent CLI 2026.09.26-dd393fe
Agent-Model: auto
Agent-Session: local session, transcript at /home/crackauc/sandbox/agent-jobs/OptimalUncertaintyQuantification.jl/jobs/54-cursor/log.txt on amdci2.julia.csail.mit.edu
ChrisRackauckas-Claude pushed a commit to ChrisRackauckas-Claude/OptimalUncertaintyQuantification.jl that referenced this pull request Sep 26, 2026
No QA opt-outs: leave the promote_symtype ambiguity check running; it is
pre-existing and fixed at the root in PR SciML#59.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Cursor Agent <noreply@cursor.com>
Agent-Harness: Cursor Agent CLI 2026.09.26-dd393fe
Agent-Model: auto
Agent-Session: local session, transcript at /home/crackauc/sandbox/agent-jobs/OptimalUncertaintyQuantification.jl/jobs/55-cursor/log.txt on amdci2.julia.csail.mit.edu
ChrisRackauckas and others added 3 commits September 26, 2026 10:36
Unwrap Inequality/Equation args in underlying_random_variables so
ℙ(Q ≳ c)/ℙ(Q ≲ c) discover the RV (Flood fixtures); drop unused Chain;
import Operator from SymbolicUtils (owner).

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Cursor Agent <noreply@cursor.com>
Agent-Harness: Cursor Agent CLI 2026.09.26-dd393fe
Agent-Model: auto
Agent-Session: local session, transcript at /home/crackauc/sandbox/agent-jobs/OptimalUncertaintyQuantification.jl/jobs/54-cursor/log.txt on amdci2.julia.csail.mit.edu
Check isinteger before Int(...) so 𝔼(Q^2.5) raises the descriptive
raw-moment error instead of InexactError.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Cursor Agent <noreply@cursor.com>
Agent-Harness: Cursor Agent CLI 2026.09.26-dd393fe
Agent-Model: auto
Agent-Session: local session, transcript at /home/crackauc/sandbox/agent-jobs/OptimalUncertaintyQuantification.jl/jobs/54-cursor/log.txt on amdci2.julia.csail.mit.edu
get_variables returns the leaf itself for z(t), a[1], and Differential(t)(z);
treat that as a base case so group lookup does not StackOverflow.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Cursor Agent <noreply@cursor.com>
Agent-Harness: Cursor Agent CLI 2026.09.26-dd393fe
Agent-Model: auto
Agent-Session: local session, transcript at /home/crackauc/sandbox/agent-jobs/OptimalUncertaintyQuantification.jl/jobs/54-cursor/log.txt on amdci2.julia.csail.mit.edu
Qualified ModelingToolkit.getdefault failed
check_all_qualified_accesses_via_owners; route through the
owner package (direct dep) and drop the QA ownership ignore.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Cursor Agent <noreply@cursor.com>
Agent-Harness: Cursor Agent CLI 2026.09.26-dd393fe
Agent-Model: auto
Agent-Session: local session, transcript at /home/crackauc/sandbox/agent-jobs/OUQ-b/jobs/54-cursor/log.txt on amdci2.julia.csail.mit.edu
ChrisRackauckas added a commit that referenced this pull request Oct 3, 2026
* Import @random_variables explicitly in the umbrella package.

The precompile workload uses the macro by name; ExplicitImports flags that
as an implicit import even though @reexport already exports it.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Cursor Agent <noreply@cursor.com>
Agent-Harness: Cursor Agent CLI 2026.09.26-dd393fe
Agent-Model: auto
Agent-Session: local session, transcript at /home/crackauc/sandbox/agent-jobs/OptimalUncertaintyQuantification.jl/jobs/55-cursor/log.txt on amdci2.julia.csail.mit.edu

* Document OUQBase public API and add a docs API page.

SciMLTesting requires every public name to have a docstring at its owning
module and an entry under docs/src; the umbrella reexports inherit those docs.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Cursor Agent <noreply@cursor.com>
Agent-Harness: Cursor Agent CLI 2026.09.26-dd393fe
Agent-Model: auto
Agent-Session: local session, transcript at /home/crackauc/sandbox/agent-jobs/OptimalUncertaintyQuantification.jl/jobs/55-cursor/log.txt on amdci2.julia.csail.mit.edu

* Approve intentional public reexports in QA allow-lists.

The umbrella and sublibraries deliberately reexport owned APIs; list those
names in reexports_allow so SciMLTesting does not treat them as leakage.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Cursor Agent <noreply@cursor.com>
Agent-Harness: Cursor Agent CLI 2026.09.26-dd393fe
Agent-Model: auto
Agent-Session: local session, transcript at /home/crackauc/sandbox/agent-jobs/OptimalUncertaintyQuantification.jl/jobs/55-cursor/log.txt on amdci2.julia.csail.mit.edu

* Bump sublibrary and umbrella QA envs to SciMLTesting 2.

reexports_allow requires SciMLTesting ≥2; the previous =1.7 floor resolved
1.8.0 and aborted both sublibrary QA lanes with MethodError.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Cursor Agent <noreply@cursor.com>
Agent-Harness: Cursor Agent CLI 2026.09.26-dd393fe
Agent-Model: auto
Agent-Session: local session, transcript at /home/crackauc/sandbox/agent-jobs/OptimalUncertaintyQuantification.jl/jobs/55-cursor/log.txt on amdci2.julia.csail.mit.edu

* Document CanonicalMoments quadratic solvers and approve Base reexports.

SciMLTesting 2 requires docstrings for the exported quadratic root helpers and
flags Base.denominator/numerator as public reexports of the Stieltjes API.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Cursor Agent <noreply@cursor.com>
Agent-Harness: Cursor Agent CLI 2026.09.26-dd393fe
Agent-Model: auto
Agent-Session: local session, transcript at /home/crackauc/sandbox/agent-jobs/OptimalUncertaintyQuantification.jl/jobs/55-cursor/log.txt on amdci2.julia.csail.mit.edu

* Import Operator from SymbolicUtils; mark #54 Aqua ambiguity broken.

ExplicitImports requires importing Operator from its owning module. The
pre-existing promote_symtype ambiguity stays tracked under issue #54.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Cursor Agent <noreply@cursor.com>
Agent-Harness: Cursor Agent CLI 2026.09.26-dd393fe
Agent-Model: auto
Agent-Session: local session, transcript at /home/crackauc/sandbox/agent-jobs/OptimalUncertaintyQuantification.jl/jobs/55-cursor/log.txt on amdci2.julia.csail.mit.edu

* Revert Aqua ambiguities broken marker from OUQBase QA.

No QA opt-outs: leave the promote_symtype ambiguity check running; it is
pre-existing and fixed at the root in PR #59.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Cursor Agent <noreply@cursor.com>
Agent-Harness: Cursor Agent CLI 2026.09.26-dd393fe
Agent-Model: auto
Agent-Session: local session, transcript at /home/crackauc/sandbox/agent-jobs/OptimalUncertaintyQuantification.jl/jobs/55-cursor/log.txt on amdci2.julia.csail.mit.edu

* Correct quadratic closed-form docstring stability claims.

Each form loses precision on one root when b^2 >> |4ac|; none is uniformly
more stable. Document that fagnano_mod is NaN for b == 0, and drop the
unverified Golub-Welsch wording on StengerCanonicalMoments.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Cursor Agent <noreply@cursor.com>
Agent-Harness: Cursor Agent CLI 2026.09.26-dd393fe
Agent-Model: auto
Agent-Session: local session, transcript at /home/crackauc/sandbox/agent-jobs/OptimalUncertaintyQuantification.jl/jobs/55-cursor/log.txt on amdci2.julia.csail.mit.edu

* Document scalar @random_variables bounds as numeric literals.

The scalar Independent form splices bound AST without evaluating caller
bindings, so named (lo, hi) stored (:lo, :hi). Fix the docstring example,
state the restriction, and assert getbounds on the documented literals.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Cursor Agent <noreply@cursor.com>
Agent-Harness: Cursor Agent CLI 2026.09.26-dd393fe
Agent-Model: auto
Agent-Session: local session, transcript at /home/crackauc/sandbox/agent-jobs/OptimalUncertaintyQuantification.jl/jobs/55-cursor/log.txt on amdci2.julia.csail.mit.edu

* Import Symbolics in umbrella QA for @random_variables bounds test.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Cursor Agent <noreply@cursor.com>
Agent-Harness: Cursor Agent CLI 2026.09.26-dd393fe
Agent-Model: auto
Agent-Session: local session, transcript at /home/crackauc/sandbox/agent-jobs/OptimalUncertaintyQuantification.jl/jobs/55-cursor/log.txt on amdci2.julia.csail.mit.edu

---------

Co-authored-by: ChrisRackauckas-Claude <accounts@chrisrackauckas.com>
Co-authored-by: Cursor Agent <noreply@cursor.com>
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: ~/sandbox/goals/ci-green/work/cig-ouq-59-merge/log.txt (local transcript, amdci2)
@ChrisRackauckas
ChrisRackauckas marked this pull request as ready for review October 3, 2026 13:51
@ChrisRackauckas
ChrisRackauckas merged commit 214f85b into SciML:main Oct 3, 2026
21 of 24 checks passed
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