Skip to content

feat(sona): in-repo Darwin Pareto frontier (ADR-353 / ADR-335 WP31) - #1224

Draft
ruvnet wants to merge 6 commits into
mainfrom
claude/focused-darwin-rkdqv7
Draft

ruvnet wants to merge 6 commits into
mainfrom
claude/focused-darwin-rkdqv7

Conversation

@ruvnet

@ruvnet ruvnet commented Oct 16, 2026

Copy link
Copy Markdown
Owner

Hypothesis

Given a set of N candidate configurations from a Darwin evolutionary
generation, each scored on M objectives (the shape
schemas/optimization-manifest-v1.json's promotion.pareto.objectives
already declares per repository),

when the Pareto frontier is computed via three independent in-repo Rust
algorithms — brute-force all-pairs (the formal definition), NSGA-II's fast
non-dominated sort, and a 2D-specialized O(N log N) divide-and-conquer
skyline (Kung, Luccio & Preparata, 1975) —

then all three must return bit-identical frontier membership on every
generated test instance, and at least one in-repo algorithm must
measurably outperform naive brute force at Darwin-lineage-relevant N,

subject to: zero external dependency in the new code path, deterministic
output for fixed input ordering, and the full pre-existing ruvector-sona
test suite remaining green.

ADR-335 Decision §6
flagged, as an explicit open item ("WP31"), that darwin.ts's
selection: "pareto" depends entirely on the external npm package
@metaharness/darwin@^0.9.1, and asked for either an in-repo implementation
or an explicit rationale for keeping the dependency. No Rust crate in this
workspace implemented Pareto dominance (grep -ri pareto crates/ returned
nothing). This PR builds the in-repo alternative.

Architecture

New module crates/sona/src/darwin_pareto.rs (sibling to the existing
darwin_guard.rs reward-hacking screen, ADR-271): Direction, dominates,
brute_force_frontier, nsga2_frontier, kung_frontier_2d,
select_frontier (dispatcher), crowding_distance, and
is_dominated_by_frontier — the literal require_non_dominated gate from
schemas/optimization-manifest-v1.json. No other crate changed; no new
dependencies.

Not done in this PR (explicitly scoped out, see ADR-353 Implementation
Plan): wiring this module into darwin.ts's actual selection: "pareto"
call site. @metaharness/darwin@^0.9.1 remains the live dependency. This PR
ships the verified, benchmarked in-repo alternative; retiring the external
dependency is a separate, TypeScript-side FFI/WASM design decision.

Files changed

  • crates/sona/src/darwin_pareto.rs (new) — core module + 11 tests
  • crates/sona/src/lib.rs — pub mod darwin_pareto;
  • crates/sona/benches/darwin_pareto_bench.rs (new) — Criterion scaling benchmark
  • crates/sona/examples/darwin_pareto_frontier.rs (new) — runnable demo against a synthetic HNSW ef_search Darwin generation
  • crates/sona/Cargo.toml — new [[bench]] entry
  • docs/adr/ADR-353-in-repo-darwin-pareto-frontier.md (new)
  • docs/research/nightly/2026-10-16-darwin-pareto-frontier/README.md + gist.md (new)

Benchmark command

cargo test -p ruvector-sona --lib
cargo run -p ruvector-sona --release --example darwin_pareto_frontier
cargo bench -p ruvector-sona --bench darwin_pareto_bench -- --quick

rustc 1.97.0 (2d8144b78 2026-07-07), Linux x86_64, release/bench profile.

Real benchmark results

N baseline (brute force) candidate_A (NSGA-II) candidate_B (Kung 2D)
100 2.03 µs 10.81 µs (5.3x slower) 2.65 µs (1.3x slower)
500 10.10 µs 921.72 µs (91.3x slower) 26.86 µs (2.66x slower)
2,000 90.94 µs 16.32 ms (179.5x slower) 85.19 µs (6% faster)
5,000 472.28 µs 124.67 ms (264.0x slower) 299.39 µs (58% faster)
20,000 not measured (cost) not measured (cost) 1.79 ms
100,000 not measured (cost) not measured (cost) 15.42 ms

Correctness: cargo test -p ruvector-sona --lib → 115 passed, 0 failed
(11 new tests, including 400 randomized cross-validation trials at M=2,3,4
objectives — zero disagreements with the brute-force ground truth across
407 total generated/hand-authored cases).

Honest finding (not smoothed over)

The initial design assumption — NSGA-II would be "the right choice once a
Flywheel lineage accumulates many candidates," based on its textbook
complexity class — is falsified by the benchmark above. NSGA-II's
domination-count pass does unconditional O(N²) work with no early exit;
brute force's per-point scan exits as soon as it finds one dominator, which
captures nearly all the available speedup on this sparse-frontier random
test data. Only kung_frontier_2d's genuinely different O(N log N)
complexity class produces a real, measured win, and only above a crossover
between N=2,000 and N=5,000. The module's doc comments were rewritten
mid-run to state the measured result instead of the original assumption.
Full writeup, including the reasoning and references (Deb et al. 2002,
Kung/Luccio/Preparata 1975), is in the gist.

Acceptance result

ACCEPT (correctness hypothesis)
REJECT/falsified (nsga2_frontier performance sub-claim — reported honestly, not hidden)
ACCEPT (kung_frontier_2d performance sub-claim, N>=2,000)

Darwin / Flywheel result

No live evolutionary search was run — this PR is the infrastructure
Darwin's pareto selection mode depends on, verified against the formal
definition of Pareto dominance (not against @metaharness/darwin's
unexamined internals, per the "no unverified external comparison" rule).
Flywheel evidence = this PR's commits, tests, and the two research
documents; no signed witness-chain tool for nightly-research provenance
exists in this repository (consistent with prior nightly findings).

Security review

No new attack surface: pure computation over caller-supplied f64 slices,
no I/O, no unsafe code, no new dependencies, zero live callers today.
kung_frontier_2d panics (fail-fast, tested) rather than silently
mis-answering for objectives.len() != 2.

Main limitations

  • No live integration into darwin.ts yet (explicitly scoped out — see ADR-353).
  • Only M=2 has a fast specialized path; M>2 falls back to nsga2_frontier, which this benchmark shows losing to brute force for M=2 (acceptable since it's never reached there, but it's the only M>2 option).
  • Brute force / NSGA-II were not measured past N=5,000 on measurement-cost grounds (NSGA-II at N=50,000 was estimated at ~12.5s/iteration).
  • No WASM build or MCP surface tested this run.

Production recommendation

Merge as-is (purely additive, zero blast radius, no existing callers). Treat
the darwin.ts FFI integration that would actually retire
@metaharness/darwin as a separate, explicitly scoped follow-up PR (see
ADR-353 Implementation Plan item 2).

Full detail in ADR-353,
research README,
and gist.


🤖 Generated with claude-flow

https://claude.ai/code/session_019f2uhtcYLS2APHudjo9RXz


Generated by Claude Code

claude and others added 6 commits October 16, 2026 07:38
Closes the correctness half of ADR-335 WP31: no Rust crate in this
workspace implemented Pareto dominance, so darwin.ts's `pareto`
selection mode depends entirely on the external npm package
`@metaharness/darwin@^0.9.1`.

Adds `ruvector_sona::darwin_pareto` with three independent frontier
algorithms (brute-force ground truth, NSGA-II fast non-dominated
sort, and a 2D-specialized O(N log N) divide-and-conquer skyline),
a `select_frontier` dispatcher, crowding-distance diversity scoring,
and the literal `require_non_dominated` gate from
schemas/optimization-manifest-v1.json. Verified against brute-force
ground truth across 407 randomized and hand-authored cases (M=2,3,4
objectives) with zero disagreements.

Co-Authored-By: claude-flow <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_019f2uhtcYLS2APHudjo9RXz
Criterion benchmark comparing baseline_brute_force, candidate_a_nsga2,
and candidate_b_kung_2d at N up to 100,000. Surfaced a falsified
sub-hypothesis: nsga2_frontier (no early exit) is consistently slower
than early-exit brute force on sparse-frontier data, not faster as
originally assumed from its textbook complexity class alone. Only
kung_frontier_2d shows a measured win, above a crossover around
N=2,000-5,000. Doc comments in darwin_pareto.rs were corrected to
state the measured result.

Also adds a runnable example demonstrating the frontier/gate against
a synthetic HNSW ef_search Darwin generation.

Co-Authored-By: claude-flow <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_019f2uhtcYLS2APHudjo9RXz
README.md and gist.md for the 2026-10-16 nightly run: hypothesis,
benchmark methodology and raw results, the falsified NSGA-II
performance sub-claim, ecosystem fit, practical/long-horizon
applications, and falsification criteria.

Co-Authored-By: claude-flow <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_019f2uhtcYLS2APHudjo9RXz
Records the decision to close the correctness half of ADR-335 WP31
with crates/sona/src/darwin_pareto.rs, the benchmark evidence
(including the falsified nsga2_frontier performance assumption), and
explicitly scopes the darwin.ts FFI integration that would retire the
@metaharness/darwin dependency as separate follow-up work.

Co-Authored-By: claude-flow <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_019f2uhtcYLS2APHudjo9RXz
Auto-updated by the session-start hook's self-update mechanism
(.claude/helpers/, signed manifest), unrelated to this branch's
Darwin Pareto frontier research. Committed separately so it is not
mixed into the research commits.

Co-Authored-By: claude-flow <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_019f2uhtcYLS2APHudjo9RXz
…8/0349)

cargo audit started failing on this PR's head after four rustls
advisories were published 2026-10-14 (TLS secret exposure in Debug
impls, Brotli cert-decompression memory amplification, ServerHello
downgrade, and buffered-data-after-ECH-rejection). This is unrelated
to the Pareto frontier change in this branch: rustls is a transitive
dependency (via reqwest -> hyper-rustls), Cargo.lock was otherwise
untouched by this PR, and the same advisories would fail an audit of
main's identical Cargo.lock today. Patch bump only (2-line Cargo.lock
diff, no API changes per cargo's own semver-compatible resolution);
verified with `cargo check -p ruvector-core`, a central crate that
pulls rustls transitively.

Co-Authored-By: claude-flow <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_019f2uhtcYLS2APHudjo9RXz

ruvnet commented Oct 16, 2026

Copy link
Copy Markdown
Owner Author

CI: cargo audit (RustSec advisories) — not caused by this PR, fix ported in

cargo audit failed on this branch's head with 4 errors, all against the transitive rustls dependency (pulled in via reqwest → hyper-rustls):

  • RUSTSEC-2026-0346 — Debug impls expose TLS secrets
  • RUSTSEC-2026-0347 — buffered app data sent after ECH rejection
  • RUSTSEC-2026-0348 — Brotli cert-decompression memory amplification
  • RUSTSEC-2026-0349 — unauthenticated ServerHello downgrade

All four advisories are dated 2026-10-14 — published this week. This PR never touched Cargo.lock (verified: no commit in this branch's range changes it) and adds zero new dependencies, so the vulnerable rustls 0.23.45 resolution was already present in main's lockfile; an audit of main today would fail identically. Confirmed via cargo audit's own log: RUSTSEC-2026-0346's advisory-db entry postdates main's last successful cargo audit run (2026-10-14 09:47 UTC).

A fix exists (the advisories' own Solution: Upgrade to >=0.23.46), so I ported it rather than just reporting: 60e1c69 bumps rustls 0.23.45 → 0.23.46 in Cargo.lock (2-line diff, patch version only, no API changes — cargo update -p rustls --precise 0.23.46 resolved cleanly under the existing Cargo.toml version requirements). Verified with cargo check -p ruvector-core, a central crate that pulls rustls transitively through the same reqwest path.


Generated by Claude Code

ruvnet commented Oct 16, 2026

Copy link
Copy Markdown
Owner Author

CI: Tests (core-platform) — not caused by this PR, pre-existing on main

The failing test is mcp-brain-server::graph::rebuild::tests::reads_stay_responsive_during_rebuild_and_result_is_exact. This PR's diff is entirely within crates/sona/ and docs — it never touches mcp-brain-server.

I checked whether this reproduces on main independently of this branch: main's own Workspace CI run from 2026-10-14 (run 38543790989, job 115784733207, on main's commit 2a257cdba7/46d816ddc4, the exact commit this branch forked from) shows the identical failure — same test, same "680 passed, 1 failed, 1 skipped" summary. Since it failed deterministically on two independent runs of the same commit two days apart, this isn't a flake to re-run; it's a reproducible pre-existing failure on main, unrelated to this PR's crate.

No fix for it is in scope here — doing so would mean debugging an unrelated concurrency test in a crate this PR doesn't touch, which would widen the PR well beyond its stated change. Flagging it as-is; happy to open a separate issue/PR for it if that's useful.


Generated by Claude Code

ruvnet commented Oct 16, 2026

Copy link
Copy Markdown
Owner Author

CI: Tests (core-and-rest-heavy) — not caused by this PR, looks like a pre-existing flake

Failing test: ruvector-dag::integration sona_tests::test_micro_lora_adaptation. The name coincidentally mentions "sona," but I verified it has no code relationship to this PR's change: crates/ruvector-dag/Cargo.toml has no dependency on the ruvector-sona crate at all — ruvector_dag::sona (used via use ruvector_dag::sona::*; in the test) is a completely separate, self-contained module at crates/ruvector-dag/src/sona/ with its own MicroLoRA implementation. This PR only touches crates/sona/ (the unrelated crate).

The test itself (crates/ruvector-dag/tests/integration/sona_tests.rs:7) constructs a fresh MicroLoRA, takes one gradient step, and asserts diff > 0.0 ("output changed after adaptation") — a shape that's flake-prone if the LoRA weights are randomly initialized and a one-step update can occasionally land on a near-zero diff. main's own last Workspace CI run of this same job (2026-10-14) passed, which is consistent with a flake rather than a systemic break.

I attempted the one permitted re-run to confirm (rerun-failed-jobs on run 38869439214), but GitHub rejected it: This workflow is already running (other jobs in the same run were still in progress). I'll re-run once the run finishes, and will report back if it fails again (which would mean this needs real investigation rather than being a flake).


Generated by Claude Code

ruvnet commented Oct 16, 2026

Copy link
Copy Markdown
Owner Author

CI: Tests (core-and-rest) — not caused by this PR, timing-threshold flake

Failing test: ruvector-mincut-gated-transformer::verification test_gemm_simd_speedup (crates/ruvector-mincut-gated-transformer/tests/verification.rs:147). No relation to this PR: ruvector-mincut-gated-transformer has no dependency on ruvector-sona, and the test itself is a wall-clock Instant::now() comparison of scalar vs. SIMD GEMM throughput — a classic CI-noisy-neighbor-sensitive timing assertion, unrelated to any correctness path this PR touches.

This is the third unrelated test-infrastructure failure surfacing on this PR's CI matrix (alongside the already-reported mcp-brain-server rebuild-responsiveness failure, reproduced identically on main, and the ruvector-dag SONA-adaptation flake). Given the pattern, I won't file a separate comment for every further timing/concurrency test that trips in this ~75k-test workspace matrix unless something looks structurally different from these three; the fix for this PR remains scoped to crates/sona/darwin_pareto.rs and the already-ported rustls security bump.


Generated by Claude Code

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