audit: remediate all 106 findings from the July 2026 ecosystem audit - #9
Merged
Conversation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DEAKcbnLVP8iSXub2Pqor2
EV-07: Individual::set_fitness now panics on NaN (documented invariant); best()/worst()/sort_by_fitness() are NaN-safe via a total order that ranks NaN strictly worst. EV-08: best()/worst()/sort_by_fitness() delegate to FitnessValue::is_better_than() (new cmp_by_quality helper) instead of a to_f64() scalar, fixing wrong results for ParetoFitness with infinite crowding distances. EV-13: NSGA-II crowding distance for parent selection is recomputed per non-dominated front (Deb 2002) via recompute_crowding_distance_per_front, replacing the whole-population computation in step/step_bounded/run/run_bounded. EV-28: genome_mut() and new set_genome() clear the cached fitness/evaluated flag. EV-84: binary tournament draws two distinct competitors (sample without replacement). EV-85: closure MultiObjectiveFitness replaced by ClosureMultiObjective wrapper with an explicit objective count instead of hardcoded 2. Regression tests added for each finding. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DEAKcbnLVP8iSXub2Pqor2
EV-27: SubtreeMutation now derives its replacement-subtree depth budget from max_depth - depth(mutation point) and accounts for generate_grow's +1 growth, so the genome max_depth invariant is preserved (with a terminal fallback guard). EV-71: bounded SBX now uses Deb & Agrawal's bounds-aware spread factor (truncated beta_l/beta_u per gene) so children land inside [min,max] by construction with no boundary probability atom, replacing the old clamp-only path. EV-72: split the conflated probability into per-pair crossover_probability (default 0.9, reported by the trait) and per-gene exchange_probability (default 0.5, canonical), with distinct fields, builders, and docs. EV-101: hand-written Default for SwapMutation/PermutationSwapMutation/InsertMutation delegates to new() (count = 1) instead of the derived count = 0 no-op. EV-102: unbounded PolynomialMutation applies a local Gaussian perturbation (sigma default 0.1*(1+|x|), configurable) instead of fabricating +/-1e10 bounds. EV-103: MutationOperator::mutation_probability now returns Option<f64>, reporting None for the length-dependent 1/n default rather than a false 1.0. EV-104: TournamentSelection samples with replacement by default (canonical); without_replacement() retains the distinct-competitor variant; determinism docs fixed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DEAKcbnLVP8iSXub2Pqor2
…EV-62, EV-97 CMA-ES (cmaes.rs): - EV-01: replace the broken hand-rolled cyclic-Jacobi routine (which never mutated its input and returned wrong/negative eigenvalues) with nalgebra::SymmetricEigen. Add eigenpair/positivity/reconstruction tests plus a seeded 5-D Rosenbrock convergence test. - EV-36: evaluate the bound-repaired (feasible) point but adapt the distribution (m/C/paths/sigma) from the UNREPAIRED sample; add an optional quadratic boundary penalty. Best-solution tracking moved to step() and reports the feasible point. - EV-37: recompute the eigensystem on the correct per-generation cadence max(1, floor(1/(10 n (c1+cmu)))) instead of a factor-of-lambda too infrequent. - EV-38: replace the trace-only eigendecomposition test with real eigenvalue/eigenvector/reconstruction assertions. Self-adaptive ES (self_adaptive.rs): - EV-05/EV-24: swap the log-normal learning rates so the shared once-per- individual deviate carries tau'=1/sqrt(2n) and per-coordinate deviates carry tau=1/sqrt(2 sqrt n) (Beyer & Schwefel); fix LearningRates::for_dimension and docs. - EV-97: isotropic case uses tau0 = 1/sqrt(n). - EV-62: rename the 1e-10 constant to SIGMA_UNDERFLOW_FLOOR (honest doc) and add a configurable, problem-scaled min_sigma (default 1e-8*initial_sigma). Evolution Strategy (evolution_strategy.rs): - EV-40: default self-adaptive ES now uses (mu,lambda) comma selection; plus remains an explicit option; docs explain why elitism suppresses sigma self-adaptation. Thread the configurable min_sigma through the mutation path. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DEAKcbnLVP8iSXub2Pqor2
Redesign the operator-parameter learner as an honest Thompson-sampling bandit and wire it into SimpleGA; fix the Gamma/Beta/log-moment estimators; add turbofish-free builder entry points and build-time config validation. - EV-23/EV-21: ThompsonSamplingTuner — each tunable parameter is discretized into arms, each arm holds a Beta posterior over P(improve | arm); Thompson arm-selection applies the arm VALUE (never the Beta draw). Wired into SimpleGA via .adaptive_operators(ThompsonConfig) + run_adaptive(); example and integration test exercise the real loop and assert feedback flows. - EV-22: GammaPosterior is an honest rate posterior; adds posterior_mean_of_mean() = beta/(alpha-1); eta params no longer shoehorned into an exponential likelihood. - EV-61: LogNormalPosterior -> RunningLogMoments; Welford variance with no small-n prior contamination. - EV-95: BetaPosterior::observations() = (alpha-alpha0)+(beta-beta0). - EV-96: PolynomialDecay doc formula corrected to match the implementation. - EV-35: SimpleGABuilder::real_valued()/bit_string()/permutation() — zero turbofish; sphere_optimization example updated + negation comment fixed. - EV-86: build() validates population/elite/crossover-prob/bounds with typed Configuration errors. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DEAKcbnLVP8iSXub2Pqor2
…V-66, EV-67, EV-68, EV-69, EV-70, EV-98, EV-99, EV-100 Bradley-Terry (bradley_terry.rs): - EV-06: recompute_all() is now driven from process_pairwise so the live loop re-fits the MLE. - EV-67: genuine Gaussian log-strength prior (NR) + Gamma pseudo-count prior (MM) keep all-win/all-loss finite. - EV-25/EV-66: strength-scale covariance via delta method from the sum-to-zero-constrained Fisher pseudo-inverse (ridge hack dropped); NR and MM now report Var(pi) on the same scale. - EV-65: Armijo sufficient-INCREASE condition (sign fixed) with a testable backtracking line search. Aggregation (aggregation.rs): - EV-06: process_pairwise re-fits Bradley-Terry before returning fitness. - EV-98: ImplicitRanking variance propagated to the score scale; Elo variance given a positive steady-state floor. Selection (selection_strategy.rs): - EV-68: find_informative_pair excludes the already-chosen index (no self-pairs). - EV-69: exploration/coverage bonuses normalized by mean population variance (model-agnostic). - EV-70: zero-variance/known pairs score ~0 (not max); only truly unobserved pairs get the max sentinel. - EV-99: entropy consistently in nats; sentinel = ln(2). - EV-100: softmax inverse-CDF fallback picks the last index, not index 0. Session/algorithm (session.rs, algorithm.rs): - EV-26/EV-64: update_fitness* are pure setters; evaluation_count is owned solely by the presented-id loop (exactly once per response, symmetric in pairwise). - EV-63: elites keep their CandidateId (and history) across generations. Adds regression tests for every finding (lib + tests/e-interactive_audit.rs). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DEAKcbnLVP8iSXub2Pqor2
…58, EV-59, EV-60, EV-91, EV-92, EV-93, EV-94 Genome-layer audit remediation: - EV-03: CompositeGenome trace round-trip now delegates to each component's own to_trace/from_trace, namespacing entries under "first/"/"second/" — no hardcoded encoding prefixes. Works for Permutation/Tree components. - EV-04: TreeGenome trace encode/decode is now lossless (function -> index in the stable F::functions(); terminal -> (discriminant, payload) via new Terminal::encode/decode). from_trace(to_trace(g)) reproduces g exactly. - EV-19/EV-20/EV-55: distance() panics on structural mismatch (was silent 0.0 / truncation); added try_distance() -> Result on the trait and per type. - EV-56: added Bounds::try_new (rejects min > max); normalize()/denormalize() handle degenerate min==max (0.5 / min) instead of dividing by zero. - EV-57: added length-aware variation operators for DynamicRealVector in src/genome/dynamic_ops.rs (cut_and_splice + DynamicGaussianMutation). - EV-58: DynamicRealVector::generate no longer panics on empty bounds; added try_generate() -> Result for the degenerate case. - EV-59: RealVector/BitString/Permutation from_trace distinguish MissingAddress (stop) from a present-but-wrong-typed choice (TypeMismatch error). - EV-60: iterative eval/depth/size + explicit iterative teardown for deep trees (a Drop impl is impossible — E0509 in the un-owned operator layer). - EV-91: DynamicRealVector to_trace/from_trace derive the gene address from trace_prefix() so it cannot diverge. - EV-92: renamed new_unchecked -> from_vec_unchecked with documented invariants and a debug_assert!(is_valid). - EV-93: EvolutionaryGenome::distance is now a required trait method. - EV-94: documented the MultiBounds-as-length convention on generate() and added honest per-type constructors (generate_with_len / generate_with_depth). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DEAKcbnLVP8iSXub2Pqor2
…, EV-90
Make the fugue_integration layer a genuine "evolution as Bayesian inference"
pipeline over the Boltzmann posterior pi_beta(x) ∝ p(x)·exp(beta·f(x)).
- EV-16: EvolutionarySMC is now a valid tempered SMC sampler — incremental
importance weights w_t = exp((beta_t - beta_{t-1})·f(x)) from the pre-move
state, accumulated across non-resampling steps, self-normalised, ESS-triggered
systematic resampling with weights reset to uniform, and pi_beta-invariant MH
mutation/crossover rejuvenation. Regression test matches the analytic Gaussian
conjugate posterior.
- EV-52: to_weighted_trace runs a real fugue `factor(beta·f)` model through the
new TraceScoringHandler so total_log_weight() == beta·f(x) (log_factors), not 0.
- EV-51: effect handlers rewritten on fugue's real Handler contract
(TraceScoringHandler, RecordingHandler with correct log-weight bookkeeping);
the ad-hoc "Poutine handlers" are honestly renamed to operation hooks and the
stale/zero per-choice logp is no longer fabricated.
- EV-90: EvolutionStep MH acceptance uses the full target incl. the prior, so
out-of-bounds proposals are rejected; stationary law is the on-bounds Boltzmann
posterior (test: no escape + mean matches truncated-exponential).
- EV-53: HBGA replaced by BayesianAdaptiveGA — conjugate Beta/Gamma posteriors
over per-operator success probability + improvement rate, Thompson sampling
each generation (renamed honestly: single-level, not "hierarchical").
- EV-54: gaussian_mutation / bounded_mutation use rand_distr::Normal(0, sigma)
so the perturbation std is exactly sigma (test on sample std).
- EV-17/EV-18: examples/bayesian_evolution.rs runs a genuine end-to-end pipeline
through the layer (fugue Model/Handler/factor); module docs state the exact
math; integration tests in tests/e_integration_bayesian.rs.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DEAKcbnLVP8iSXub2Pqor2
… EV-44 EV-49 EV-50 EV-73 EV-79 EV-80 EV-81 EV-82 EV-83 EV-88 EV-105 Island model (island.rs): - EV-12 persistent per-island StdRng seeded once from the master RNG -> seeded runs are bit-reproducible even with parallel island evaluation. - EV-11 FullyConnected/Star migration broadcasts to ALL topology targets. - EV-41 immigrants replace the island's worst members, never the best. - EV-82 evaluation counter counts only newly-evaluated individuals. - EV-83 saturating elite arithmetic (no usize underflow for large elitism). Steady-state (steady_state.rs): - EV-43 generate/evaluate exactly offspring_count children. - EV-42 ReplaceRandom/ReplaceWorst/TournamentWorst replace unconditionally; new ReplaceIfBetter is the elitist accept-if-better option. - EV-44 optional prevent_duplicates(bool) genome de-duplication (O(n)). UMDA (eda/umda.rs): - EV-39 rejection sampling from the truncated region (retry 100 then clamp). - EV-81 Bessel (n-1) sample variance. - EV-80 selection uses is_better_than, not to_f64. - EV-79 builder validates ranges in build() (Result) instead of clamping. - EV-10 tests: seeded UMDA beats a same-budget random-search baseline and the learned model converges to the optimum (via new run_with_model). Convergence (diagnostics/convergence.rs): - EV-14 evolutionary_rhat truncates chains to the common minimum length. - EV-49 target-fitness check reads the tracked running best. - EV-50 Stagnation criterion honors its configured threshold. - EV-88 R-hat uses incremental prefix-sum statistics (no full-history rescan). Termination (termination/mod.rs): - EV-73/EV-105 FitnessStagnation uses best-so-far window improvement. Benchmarks (fitness/benchmarks.rs): - EV-15 DixonPrice::optimal_solution() uses the canonical 1-based exponent. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DEAKcbnLVP8iSXub2Pqor2
…icy regression suite - tests/property_tests.rs: replace rand::thread_rng() with StdRng seeded from a proptest-generated any::<u64>() input in all 10 RNG-driven proptests, so failures reproduce byte-for-byte via proptest's own seed/shrink file instead of drawing fresh entropy on every re-run. - tests/e_tests_seeded_determinism.rs (new): for SimpleGA, CMA-ES, (mu+lambda)-ES, UMDA, and NSGA-II, assert two runs with the same StdRng seed produce an identical best genome/fitness (or final population), and two runs with different seeds (almost surely) differ. - tests/e_tests_nan_policy.rs (new): assert Population::evaluate, SimpleGA::run, EvolutionStrategy::run, and ContinuousUMDA::run all panic with a documented message when a fitness function returns NaN, per the EV-07 wave-A policy. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DEAKcbnLVP8iSXub2Pqor2
- EV-02: real RNG round-tripping. Add rand_chacha (serde1) and a SnapshotRng trait (ChaCha8/12/20Rng) with capture()/restore(); Checkpoint::with_rng / restore_rng thread it through. Rewrite examples/checkpointing.rs to prove bit-identical resume (20 straight vs 10 + disk checkpoint + restore + 10); add integration test tests/e-checkpoint_resume.rs. - EV-45: version compatibility now checked uniformly (JSON, binary, compressed); VersionTooOld is actually returned for pre-minimum schemas. - EV-46: CheckpointManager scans existing files on construction and continues the index after the max found (restart-safe). - EV-47: atomic writes - serialize to <path>.tmp, fsync, then fs::rename. - EV-48: configurable bincode size limit (default 256 MiB); oversized files and corrupt length prefixes return a typed TooLarge error. - EV-87: checkpoint indices zero-padded to 8 digits; load_latest orders by parsed numeric index (backward-compatible with legacy names). - EV-89: checkpoint (de)serialization errors preserve the source chain via #[source] (new SerializeError/DeserializeError variants). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DEAKcbnLVP8iSXub2Pqor2
- EV-09: install console_error_panic_hook in the wasm_bindgen(start) init so
Rust panics log real file/line instead of an opaque `unreachable` trap;
document panic semantics. JS-boundary audit: no panicking unwraps remain
(fitness helpers use saturating unwrap_or fallbacks).
- EV-32: route every fallible EvolutionError boundary through
evolution_error_to_js so JS receives structured {type, message} errors;
the previously-dead function is now live.
- EV-33: report the REAL NSGA-II evaluation count via a counting fitness
decorator (CountingMoFitness); delete the fabricated pop*gens*2 formula.
- EV-34: add a native incremental stepping API to SimpleGA
(init_run/step_generation/finish_run) and refactor run() to drive it
(behavior identical); expose a SteppedRealOptimizer in wasm with
step(n)/progress getters/early cancel.
- EV-75: remove unused serde-wasm-bindgen and wasm-bindgen-futures deps.
- EV-76: CMA-ES fitness_history now records per-generation best-so-far by
driving step() directly, instead of a single flat point.
- EV-77: add an IslandModelOptimizer wasm binding (Ring/FullyConnected/Star
topologies, best-k migration) built on the step API plus new migration
helpers (SimpleGaRun::best_genomes / SimpleGA::inject_migrants); the native
island module is unavailable in wasm (requires the parallel/rayon feature).
- Tests: native step/migration equivalence tests; host regression tests
(e_wasm_regressions.rs) plus browser wasm_bindgen tests covering the step
API, island model, CMA-ES history, real NSGA-II count, and structured errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DEAKcbnLVP8iSXub2Pqor2
…9, EV-30, EV-31, EV-74, EV-78) - EV-29: reconcile license metadata to a single MIT license (matching fugue-ppl) in fugue-evo/Cargo.toml and crates/fugue-evo-wasm/Cargo.toml; add a root LICENSE (MIT text, copyright Alex Nodeland 2025-2026); update both READMEs off the unsupported "MIT OR Apache-2.0" claim (no LICENSE-APACHE/LICENSE-MIT texts ever existed for that claim). - EV-30: verified a `path = "../fugue", version = "0.1.0"` dependency compiles cleanly against the current sibling checkout (cargo check --all-targets, cargo test --lib: 645 passed) -- but the sibling `fugue` repo is independently, concurrently under its own active audit remediation and was observed to go from green to red minutes later from unrelated in-progress edits with zero change on the fugue-evo side. A hard path dependency makes fugue-evo's own build only as stable as fugue's current, possibly-mid-edit working tree, which is exactly the fragility a crate published independently to crates.io should not have. Kept `fugue-ppl = "0.1.0"` pinned to the registry release instead, and documented (with a verified-working example) how to opt into the sibling via a local, uncommitted `[patch.crates-io]` override in README.md's new Development section. - EV-31: move crates/fugue-evo-wasm's [profile.release] (opt-level "s", LTO) to the workspace-root Cargo.toml, where cargo actually honors it; the member manifest keeps a comment pointing at the root. - EV-74: proptest unconditionally pulls in rand 0.9/rand_core 0.9/rand_chacha 0.9 alongside our own rand 0.8 stack; confirmed via `cargo tree -i` that this holds even pinned to proptest 1.7.0 and that the upstream fugue sibling has the identical duplication despite the same proptest = "1.0" pin. Documented as upstream-forced in Cargo.toml rather than "fixed" by a version bump. - EV-78: reworded the misleading "we negate because fugue-evo maximizes" comment in examples/sphere_optimization.rs (Sphere already negates internally) and fixed the printed "Best fitness" to un-negate the sum of squares so it reads as the expected near-zero, non-negative optimum; scanned other examples for the same pattern (none found; the one other "negate" comment, in symbolic_regression.rs, describes a genuine user-authored negation and is accurate as-is). - README/SPEC surgical updates: Bayesian hyperparameter learning is a wired, opt-in ThompsonSamplingTuner; the Fugue integration runs a genuine tempered-SMC/Boltzmann pipeline with a flagship bayesian_evolution.rs example; checkpointing supports bit-identical resume for the ChaCha RNG family. SPEC.md gets a dated implementation-note callout rather than a rewrite. - CHANGELOG.md: added an Unreleased section summarizing the full 2026-07 audit remediation (EV-01 through EV-106). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DEAKcbnLVP8iSXub2Pqor2
Fixes the re-verification items flagged after the 2026-07 remediation: - EV-02: add a library-level checkpoint resume path — SimpleGA::checkpoint_run / resume / run_from_checkpoint thread a SnapshotRng (ChaCha) through the run loop for bit-identical resume; un-gate the incremental stepping API for all builds; rewrite examples/checkpointing.rs to use it; add regression tests. - EV-04: add Pow to ArithmeticFunction::functions() (and protect Pow against NaN) so every function variant round-trips losslessly; harden encode_function with a debug_assert; add per-variant and Pow round-trip regression tests. - EV-17: correct the crate-level framing in lib.rs/README.md/SPEC.md so the "evolution as Bayesian inference" headline scopes to fugue_integration and the default algorithms are described as standalone EC using Trace as a container. - EV-21: document schedules.rs and adaptive.rs as unintegrated building blocks (hyperparameter/mod.rs + module docs), matching the Beta/Gamma treatment. - EV-34: add per-generation progress/cancel callbacks to all remaining WASM optimizers (BitString/Permutation/Nsga2/SymbolicRegression via the step API; ES/UMDA via new native run_with_callback hooks); add tests. - EV-35: replace the 7-param turbofish quickstart with SimpleGABuilder::real_valued() in README, lib.rs, examples, and docs. - EV-60: add a stack-safe Drop for TreeNode (mem::take teardown), make the position collectors and PointMutation iterative; add 100k-deep drop/positions/ mutation regression tests. - EV-74: pin proptest = ">=1.5, <1.7" to collapse the duplicate rand major; add a `make deps-check` (cargo tree -d) CI guard; correct the Cargo.toml/ CHANGELOG notes. - EV-83: add an island regression test for elitism > population size. - REG-1: track a pure running max (separate from the stagnation-throttled best) so target-fitness detection is not missed when stagnation_threshold > tolerance. - REG-2: correct the CHANGELOG EV-30 entry to match the actual crates.io dependency and the README's documented rationale. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DEAKcbnLVP8iSXub2Pqor2
…n (re-verification lows) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DEAKcbnLVP8iSXub2Pqor2
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DEAKcbnLVP8iSXub2Pqor2
…low-up) Flip fugue-ppl from the published crates.io release to the co-developed sibling checkout via `path = "../fugue"` (version = "0.1.0" retained), so fugue-evo's Fugue integration is finally exercised against the actual co-developed source now that fugue's 2026-07 audit remediation has landed with a green full-test gate. Adapt genome::composite trace namespacing to fugue's new Address struct (Address::new(..)/addr.as_str() replacing the former tuple-struct Address(..) constructor and .0 field); no behavior change. Reconcile the now-stale EV-30 CHANGELOG entry and README "Development" section, which previously documented the deliberate crates.io pin. Full suite green: 706 unit/integration tests + 3 doctests pass; bayesian_evolution example runs end-to-end; wasm crate cargo check clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DEAKcbnLVP8iSXub2Pqor2
…diation complete) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DEAKcbnLVP8iSXub2Pqor2
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DEAKcbnLVP8iSXub2Pqor2
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DEAKcbnLVP8iSXub2Pqor2
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DEAKcbnLVP8iSXub2Pqor2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Remediates all 106 findings (EV-01…EV-106) from the July 2026 fugue-ecosystem audit — mathematical soundness, correctness, performance, API design, docs, and packaging. No deferrals: every finding carries a final resolution in
AUDIT-2026-07.md, and every fix was independently re-verified by an adversarial review pass (106/106 verified).Highlights:
SymmetricEigen), fixed step-size adaptation and rank-μ update math (EV-01, EV-05, EV-24, …)compute_rhat, splitmix64 island-seed derivation, seed property tests (EV-106 + re-verification fixups)fugue-pplvia path + version (EV-30); CI clones the sibling fugue repo (same-named branch when it exists, elsemain)Full finding-by-finding log:
AUDIT-2026-07.md(each entry has a resolution, regression tests, and an independent re-verification verdict).Test plan
cargo test— 706 tests green against sibling fugue (post-remediation)cargo clippyclean,cargo fmt --checkclean🤖 Generated with Claude Code
https://claude.ai/code/session_01DEAKcbnLVP8iSXub2Pqor2