Conversation
WitnessHandle::materialize_partition() derived its complement-side vertex universe from the found cut set's own maximum vertex ID rather than the graph's real vertex set, silently dropping every higher-numbered vertex from both returned sides whenever the (typically small) cut set didn't happen to contain the graph's highest ID -- nearly always. This was the dominant cause of the ~50% "empty/unusable" RuVectorGraphAnalyzer::partition() results flagged as an open question by the 2026-09-05 nightly (ADR-345); reproduction on this checkout measured 99-100%. Add WitnessHandle::materialize_partition_within(universe) and switch RuVectorGraphAnalyzer::partition() to call it with the graph's actual vertex set. Also sort the HashSet-derived vertex/seed orderings in BoundedInstance's tie-breaking paths (brute_force_min_cut, search_for_cuts), removing RandomState-seeded hash order as a source of which tied-optimal witness gets returned. Adds crates/ruvector-mincut/examples/determinism_probe.rs, the reproducible probe backing this fix's evidence (see ADR-346 and docs/research/nightly/2026-09-07-deterministic-mincut-witness/). Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01CgVaCy8r8yHCWpKASuEi5v
Records the hypothesis, root-cause analysis, before/after evidence, and decision for the ruvector-mincut fix in the prior commit. Directly answers ADR-345's Open Question #2. Regenerates the ADR index entry. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01CgVaCy8r8yHCWpKASuEi5v
Full methodology, raw benchmark transcripts (baseline / fix-A-only / fix-A-plus-B across three topologies), ecosystem-fit analysis, and a standalone gist for the deterministic-mincut-witness nightly run. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01CgVaCy8r8yHCWpKASuEi5v
Open PR #965 ("structural-time keyframe retention for agent memory") independently claimed ADR-346 first (filed 2026-09-06, a day before this PR). Following this repo's established collision-resolution convention (see ADR-341's own renumbering history), the later claim renumbers. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01CgVaCy8r8yHCWpKASuEi5v
|
CI status note (not this PR's failure): the Generated by Claude Code |
ruvnet
left a comment
There was a problem hiding this comment.
Dream exact-head review — INCONCLUSIVE
The candidate addresses both identified causes: HashSet-derived traversal is sorted, and partition materialization now receives the graph's actual vertex universe. The 30-trial regression is a useful deterministic falsification test. Native, WASM-dedup, regression, supply-chain, formatting, and clippy workflows pass.
Required Workspace CI was cancelled, so the frozen native/WASM/workspace acceptance gate is incomplete. Please obtain a green exact-head Workspace CI result and retain the complete-partition assertion on sparse/non-contiguous vertex sets. No performance or cross-backend parity claim is promoted until that final gate passes.
|
Re: the review's request for a green exact-head Workspace CI result — pulled the actual job log for Since it died before any test body ran, I've used this PR's one re-run allowance: triggered Generated by Claude Code |
Summary
Nightly research run (2026-09-07) directly following up on the 2026-09-05
nightly (ADR-345, "Mincut-Gated Forgetting"), which rejected a
ruvector-agent-memorycompaction policy for two independent reasons andleft one as an explicit open question: "What specifically causes the
measured non-determinism inside
ruvector-mincut... instance constructionorder, witness materialization, or something else?"
This PR answers it.
WitnessHandle::materialize_partition()(
crates/ruvector-mincut/src/instance/witness.rs) computed the complementside
V \ Uas(0..=membership.max()).filter(not in U)-- deriving thevertex universe from the found cut set's own highest member rather than
the graph's actual vertex set. Since a minimum cut's small side essentially
never contains the graph's globally-highest vertex ID, every vertex
numbered above it was silently dropped from both returned sides. This
was the dominant cause of ADR-345's ~50% "empty/unusable" measurement;
reproduction on this checkout (with a corrected probe graph -- see ADR-347's
"A trap in the original probe") measured 99-100%.
Two fixes, both default-on, no feature flag:
WitnessHandle::materialize_partition_within(universe),and
RuVectorGraphAnalyzer::partition()switched to call it with thegraph's real
vertices()instead of guessing a universe.HashSet-derived vertex/seed orderings inBoundedInstance's tie-breaking paths (brute_force_min_cut,search_for_cuts), removingRandomStatehash-seed randomization as asource of which tied-optimal witness gets returned.
Not in scope: ADR-345's other, independent rejection cause (latency
scaling at small n) is unaffected and remains open -- see ADR-347's "Open
Questions" for the natural next nightly topic.
Note on ADR numbering: originally filed as ADR-346; renumbered to
ADR-347 after discovering open PR #965 independently claimed ADR-346 first
(filed a day earlier). See the numbering-fix commit on this branch.
Architecture
See ADR-347
for full hypothesis, decision, and rationale, and the
nightly research report
(plus gist
and raw transcripts) for the complete narrative and evidence.
Benchmark command
Three fixed topologies (n=19 brute-force path, n=21 and n=85 LocalKCut-oracle
path), 200 fresh-analyzer trials each, isolated via
git stashacrossbaseline / fix-A-only / fix-A+B states of the identical probe binary.
Real benchmark results
Fix A alone eliminates all empty/degenerate results (confirming it as the
dominant defect). Fix B closes the remaining gap to full determinism --
exactly one partition observed across all 600 post-fix trials. Latency is
unaffected by either fix beyond noise (largest delta: n=19's
1236.9ms → 1167.6ms avg/call, a 5.6% improvement attributable to sort
overhead being smaller than search-order variance, not a claimed
optimization -- this PR's scope is correctness, not speed).
Full raw transcripts (including the interim diagnostic that caught a bug in
this run's own first-draft probe graph):
raw-runs.txt.Acceptance result
ACCEPT. All of this PR's stated hard gates were met: 0% empty/degenerate
on all three topologies, exactly 1 distinct partition per topology across
200 trials, and no regression in either crate's test suite.
Darwin result
Not applicable this run -- a root-cause bug-fix investigation with exactly
one correct fix per identified defect, not a bounded-parameter-search
problem. See ADR-347 / research README for detail.
Flywheel result
No
ruvector harness flywheelCLI surface was resolvable in this checkout(
npm error could not determine executable to run). ADR-347 and thenightly research report serve as this run's evidence trail, in the same
spirit as ADR-345's, and explicitly carry forward the unresolved latency
question for the next nightly in this lineage.
Security review
No new cryptographic primitive.
materialize_partition_withinis a purefunction over already-public data (
WitnessHandle::contains); it does notchange what a witness exposes, only how completely a caller reconstructs
both sides. Fixing silent vertex loss is itself a hardening for any future
witness-auditing code that expects
.partition()'s two sides to sum to thegraph's vertex count.
Test evidence
cargo test --release -p ruvector-mincut --lib: 515 passed, 0 failed(5 pre-existing, unrelated ignores).
cargo test --release -p ruvector-mincut --doc: 27 passed, 0 failed(includes the new
materialize_partition_withindoctest).cargo test --release -p ruvector-agent-memory --features mincut-forget(the downstream consumer from ADR-345): 63 passed, 0 failed across
lib + 3 integration test binaries.
cargo clippy --release -p ruvector-mincut --lib: no new warnings.cargo fmt -p ruvector-mincut -- --check: clean.Main limitations
BoundedInstance'stwo internal code paths; real (non-synthetic) embedding graphs at larger
scale were not tested this run.
69s at n=19" finding qualitatively) is not fixed here and remains
open -- this PR only confirms neither fix worsens it.
agenticfeature's parallel query path was not touched or exercised.Production recommendation
Ship as-is: this is a default-on bug fix in already-shipped public API
(
RuVectorGraphAnalyzer::partition()), not an experimental addition. Everyexisting and future caller (
CommunityDetector,GraphPartitioner, and anyout-of-tree consumer) gets a complete, deterministic result automatically,
with no migration required.
Files changed
crates/ruvector-mincut/src/instance/witness.rs-- newmaterialize_partition_within, strengthened docs, 2 new tests.crates/ruvector-mincut/src/integration/mod.rs--partition()fixed;new
test_partition_deterministic_and_completeregression test.crates/ruvector-mincut/src/instance/bounded.rs-- sorted tie-breakingin
brute_force_min_cut/search_for_cuts.crates/ruvector-mincut/examples/determinism_probe.rs-- new,reproducible probe backing this PR's evidence.
docs/adr/ADR-347-deterministic-mincut-witness-materialization.md-- new.docs/adr/INDEX.md-- new entry, counters updated.docs/research/nightly/2026-09-07-deterministic-mincut-witness/-- new(
README.md,gist.md,raw-runs.txt).Next research
ADR-345's Open Question #1 (does
DynamicMinCut/ClusterHierarchy, useddirectly instead of
MinCutWrapper's bounded-instance sweep, avoid thelatency scaling this PR left untouched?) is the natural next nightly in
this lineage -- see ADR-347's "Open Questions" and the research README's
"Next research" for the full list.
🤖 Generated with claude-flow
https://claude.ai/code/session_01CgVaCy8r8yHCWpKASuEi5v