Skip to content

research(nightly): canonical mincut backend for agent-memory forgetting (ADR-346) - #1002

Draft
ruvnet wants to merge 3 commits into
mainfrom
claude/focused-darwin-ofxsw4
Draft

ruvnet wants to merge 3 commits into
mainfrom
claude/focused-darwin-ofxsw4

Conversation

@ruvnet

@ruvnet ruvnet commented Sep 20, 2026

Copy link
Copy Markdown
Owner

Hypothesis

Direct, non-duplicative follow-up to ADR-345 (2026-09-05,
docs/research/nightly/2026-09-05-mincut-gated-forgetting/), which
rejected ruvector-agent-memory::graph_forget::MincutGatedForgetting
(a min-cut-derived structural eviction signal for agent-memory
compaction) on two measured grounds: non-deterministic partitions from
ruvector_mincut::RuVectorGraphAnalyzer, and a 1,800-2,700x compaction
slowdown against a 100x budget. That run's own "Next Research" left an
explicit, unclaimed follow-up: repeat the experiment against a
lower-level ruvector-mincut API and, if the picture changes, re-run
the exact same benchmark (same corpus, seed, thresholds) rather than
a new one.

This PR does exactly that, using ruvector_mincut's existing (already
shipped, previously unused by this crate) ADR-117 pseudo-deterministic
canonical::source_anchored::SourceAnchoredMinCut engine in place of
RuVectorGraphAnalyzer.

Given the exact ADR-345 corpus, seed, and acceptance thresholds,
when MincutGatedForgetting-Soft/-Hard use SourceAnchoredMinCut instead
of RuVectorGraphAnalyzer for boundary-vertex detection,
then repeated calls on identical input return an identical partition,
and compaction wall-clock stays under the original 100x threshold,
subject to: the bridge-survival gap (>=15pp) and recall delta (<=2pp)
thresholds from ADR-345 apply unmodified, and tamper-detection stays
at 100%/20 trials.

Architecture

  • MincutGatedForgetting gains a backend: MincutBackend field
    (Legacy default, unchanged; new Canonical) and
    soft_canonical/hard_canonical constructors — purely additive, no
    change to any existing caller's behavior.
  • ruvector-agent-memory's (already optional, off-by-default)
    mincut-forget feature now also enables ruvector-mincut's
    canonical feature.
  • No changes to ruvector-mincut itself.

Files changed

  • crates/ruvector-agent-memory/src/graph_forget.rsMincutBackend, canonical boundary detection, new tests
  • crates/ruvector-agent-memory/Cargo.toml — enable canonical feature on the optional ruvector-mincut dep, register 2 new examples
  • crates/ruvector-agent-memory/examples/mincut_canonical_probe.rs — determinism + scaling probes, mirrors the ADR-345 probes exactly
  • crates/ruvector-agent-memory/examples/mincut_gated_forgetting_bench_canonical.rs — line-for-line copy of ADR-345's benchmark, only the backend swapped
  • docs/adr/ADR-346-canonical-mincut-backend-for-agent-memory-forgetting.md
  • docs/research/nightly/2026-09-20-canonical-mincut-forgetting/{README,gist}.md
  • docs/adr/INDEX.md — regenerated via node scripts/adr-index.mjs

Benchmark commands

cargo run --release -p ruvector-agent-memory --example mincut_canonical_probe --features mincut-forget
cargo run --release -p ruvector-agent-memory --example mincut_determinism_probe --features mincut-forget
cargo run --release -p ruvector-agent-memory --example mincut_scaling_probe --features mincut-forget
cargo run --release -p ruvector-agent-memory --example mincut_gated_forgetting_bench --features mincut-forget
cargo run --release -p ruvector-agent-memory --example mincut_gated_forgetting_bench_canonical --features mincut-forget

Real benchmark results

All numbers below are from this exact environment (Linux x86_64, release
build, rustc 1.94.1), legacy and canonical backends run back-to-back on
the same machine for a fair comparison (not compared against ADR-345's
original numbers, which were from a different machine).

Determinism (19-vertex bridge graph, 30 calls on byte-identical input):

Backend avg latency/call degenerate/empty distinct partitions
Legacy 1160.1 ms 18/30 (60%) non-repeatable
Canonical 0.116 ms 0/30 (0%) 1 (fully deterministic)

ADR-345 corpus re-run (84 entries, seed=341, thresholds unchanged):

Policy Backend Bridge Surv. Recall@10 Compaction Slowdown
CoherenceWeighted (baseline) 66.7% 100.0% 58 µs 1.0x
Soft Legacy 66.7% 100.0% 116,188 µs 2003.2x FAIL (>100x)
Hard Legacy 66.7% 100.0% 115,401 µs 1989.7x FAIL
Soft Canonical 66.7% 100.0% 3,907 µs 67.4x PASS
Hard Canonical 66.7% 100.0% 3,617 µs 62.4x PASS

Tamper detection: 20/20 both backends. Full scaling table (n=19..400) and
root-cause confirmation (DynamicGraph's DashMap-backed adjacency has no
fixed iteration order; the canonical engine fixes vertex order + a
lexicographic tie-break explicitly) are in the nightly README.

Acceptance result

REJECT (unchanged top-line outcome from ADR-345) — the mandatory
bridge-survival gate still fails for both backends (+0.0pp vs. a required
≥15pp). But this closes 2 of ADR-345's 3 open findings with hard evidence:

  • Non-determinism: fixed (100% reproducible vs. 40% agreement)
  • Performance gate: now passes (67x/62x vs. 2003x/1990x, both same corpus/env)
  • Effectiveness gate: still fails, and is now known to be independent
    of the backend bug — rules out "the bug was masking a real effect."

Darwin result

Not run — no Darwin evolution phase was applicable to this backend-swap
experiment (no tunable parameter search was in scope; the change is a
binary engine choice, not a parameterized policy).

Flywheel result

Retained as evidence in docs/research/nightly/2026-09-20-canonical-mincut-forgetting/README.md
and ADR-346, including the still-open effectiveness rejection and the
concrete, already-scoped next step (a local Gomory-Hu-tree/per-cluster cut
signal instead of a single global min-cut) for a future nightly run.

Security review

No new external dependencies, no I/O, no unsafe code beyond what
ruvector-mincut's existing canonical feature already ships. The
eviction witness chain (witnessed_compaction) is backend-agnostic and was
re-verified at 100%/20 tamper-detection trials under the new backend.
mincut-forget remains off by default; no default-build or default-runtime
behavior changes for any existing caller.

Main limitations

  • Corpus size (84 entries) kept identical to ADR-345 to preserve a strict
    apples-to-apples comparison; a materially larger corpus is now plausible
    given the canonical backend's speed but wasn't attempted here.
  • No memory (RSS) accounting added for either backend.
  • No WASM/edge build exercised.

Production recommendation

Do not promote MincutGatedForgetting to a default/recommended policy
(bridge-survival gate still fails). Do prefer SourceAnchoredMinCut over
RuVectorGraphAnalyzer for any future ruvector-mincut consumer in this
codebase that needs a repeatable partition. Next concrete step: try a
local (per-cluster-pair) cut signal instead of a global one — see
"Next research" in the nightly doc.

Research document / ADR / gist

  • docs/research/nightly/2026-09-20-canonical-mincut-forgetting/README.md
  • docs/adr/ADR-346-canonical-mincut-backend-for-agent-memory-forgetting.md
  • docs/research/nightly/2026-09-20-canonical-mincut-forgetting/gist.md

Test plan

  • cargo build --release -p ruvector-agent-memory --features mincut-forget
  • cargo test --release -p ruvector-agent-memory --features mincut-forget (66 tests pass, including 4 new canonical-backend tests)
  • cargo clippy --release -p ruvector-agent-memory --features mincut-forget --all-targets (clean, no new warnings)
  • cargo fmt -p ruvector-agent-memory
  • All 5 benchmark/probe commands above run and their raw output is reproduced in the nightly README

🤖 Generated with claude-flow

https://claude.ai/code/session_01PpkpGRcMn5JxpzQWWuiVvV


Generated by Claude Code

claude and others added 2 commits September 20, 2026 07:25
Nightly follow-up to ADR-345 (2026-09-05): attacks its two open
findings by adding MincutBackend::Canonical, wiring
ruvector_mincut::SourceAnchoredMinCut (ADR-117 pseudo-deterministic
canonical min-cut) into MincutGatedForgetting as an opt-in backend
alongside the existing RuVectorGraphAnalyzer-based default.

Measured in this repo, same environment, same ADR-345 corpus/seed:
- Determinism: 30/30 identical partitions vs. 40% agreement/60%
  degenerate for the legacy backend.
- Performance: 67.4x/62.4x compaction slowdown vs. baseline (passes
  the 100x gate) vs. 2003.2x/1989.7x for the legacy backend (fails).
- Bridge-survival effectiveness gate is unchanged (+0.0pp vs a
  required >=15pp) under both backends, so MincutGatedForgetting
  itself remains unpromoted; see ADR-346 and the nightly doc for the
  full evidence and interpretation.

Default backend and all existing soft()/hard() behavior are
unchanged; this is purely additive (soft_canonical/hard_canonical).

Co-Authored-By: claude-flow <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01PpkpGRcMn5JxpzQWWuiVvV
Documents the 2026-09-20 nightly run's hypothesis, methodology, raw
benchmark evidence, root-cause confirmation, ecosystem analysis, and
falsification criteria for the canonical mincut backend evaluated in
the companion code commit. Regenerates docs/adr/INDEX.md via the
repo's own scripts/adr-index.mjs.

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

@ruvnet ruvnet left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dream cycle exact-head review: REJECT.

Canonical min-cut is deterministic for the same ordered input and preserves 100% synthetic recall, but the frozen outcome gate fails: bridge survival is 66.7% for baseline, Soft, and Hard—+0.0 percentage points versus the required ≥15pp. Required Workspace CI was cancelled after four hours in the shard containing the changed consumer.

There is also no production caller, independent seeded/permuted holdout, restart/order qualification, or native/WASM/RVF parity for this feature path. Please treat the large speedup over the legacy implementation as bounded implementation evidence, not a promotion result, until the outcome, consumer, CI, and cross-target gates pass.

A 2026-09-21 PR review agreed with this PR's own REJECT acceptance
result but flagged that the measured speedup/determinism numbers could
be read as stronger evidence than they are. Makes explicit, in both
the ADR and the nightly doc, that they are bounded implementation
evidence for the canonical engine itself, not promotion evidence: no
production caller exists, results are single-seed/single-corpus, and
determinism was only measured within one process. Adds the
corresponding follow-ups to "Next research". No code changes.

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

ruvnet commented Sep 21, 2026

Copy link
Copy Markdown
Owner Author

Thanks for the review — responding to both parts.

On the REJECT verdict: no disagreement — this PR's own "Acceptance result" section already reports REJECT for the same reason (bridge-survival gap +0.0pp vs. the required ≥15pp, both backends). The scope point is fair though: the speedup and determinism numbers could be read as stronger than they are. Pushed a docs-only follow-up (ec37ebd0e) making explicit, in both the ADR and the nightly doc, that they're bounded implementation evidence for the canonical engine itself, not promotion evidence — and adding four items to "Next research": no production caller exists for this path, results are single-seed/single-corpus (no independent seeded/permuted holdout), determinism was only qualified within one process (no restart/order qualification), and native/WASM/RVF parity is untested. All four are now explicit limitations and open questions rather than implicit gaps.

On "Required Workspace CI was cancelled after four hours": confirmed — the Tests (core-and-rest) shard hit the job's 240-minute timeout (07:27–11:27 UTC on 2026-09-20) and was cancelled. Checked whether this is caused by this PR's diff: it isn't. The last 5 Workspace CI runs on main itself (entirely unrelated commits — the mincut publish-version fix, the optional @ruvector/mincut-wasm capability PR, the RVF backend-selection fix, and two dependency bumps) all show the identical core-and-rest shard cancelled at the same timeout. ci.yml's own inline comments document this as a chronic, ragged-edge issue across many past iterations (180min cap → bumped to 240min, still hitting it). Separately: this PR's only new Cargo feature (canonical on the optional ruvector-mincut dep) is gated behind ruvector-agent-memory's existing off-by-default mincut-forget feature, which the core-and-rest shard's plain cargo nextest run --workspace ... invocation does not enable — so nothing this PR adds should be compiled in that shard's default build at all. No fix exists yet that I can port (the real fix is splitting core-and-rest into another shard, which is a CI-infra change out of scope for this research PR). I haven't triggered a re-run — given the pattern is a base-branch-wide capacity issue rather than a one-off flake, a re-run would very likely hit the same wall.


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