Commit Graph

16 Commits

Author SHA1 Message Date
ruv 28ea21f6c8 darwin-core iter 2 — reasoning-bank: scifact bm25 tie-breaker 0.0→0.05 Δ=+0.0024 2026-06-27 11:16:56 -04:00
ruv 8dd4f77d2a darwin: iter 26 proposal — arguana weights match validated nfcorpus/scifact recipe 2026-06-26 18:40:15 -04:00
ruv 24b791d47e iter 20: scifact RRF weights bm25 0.2→0.0 (pure dense, +1.24% ndcg@10 → 0.626) 2026-06-26 18:03:43 -04:00
ruv c48f7697e4 darwin: iter 19 advance — scifact bm25 0.4→0.2 Δ+0.0165 (+2.76%)
Tested nfcorpus winner recipe (pure dense 1.0, downweight BM25) on scifact.
Result: ndcg10 0.5971→0.6136, rank 10/11 on published baselines.

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-06-26 17:59:17 -04:00
ruv 26c20f0a24 darwin: iter 18 — scifact RRF weights +3.6% (ndcg10 0.5766→0.5971)
Added scifact-specific RRF weights {dense:1.0, bm25:0.4} to DATASET_RRF_WEIGHTS,
mirroring the nfcorpus pure-dense strategy. Clinical fact verification benefits
from dense semantic matching over lexical noise. Benchmarked on 300 queries,
rank 10/11 on published leaderboard (0.5971 vs SOTA 0.722).

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-06-26 17:54:16 -04:00
ruv da6bc0ba7f darwin: iter 14 advance — nfcorpus bm25 0.2→0.0 pure-dense Δ+0.0028 2026-06-26 17:23:16 -04:00
ruv f04a369310 darwin: iter 13 advance — nfcorpus bm25 0.4→0.2, ndcg10 0.3443→0.3489 (+0.13%) 2026-06-26 17:17:07 -04:00
ruv c71937f0b2 darwin: iter 11 advance — nfcorpus bm25 weight 0.7→0.4, ndcg10 0.3372→0.3443 (+0.71%) 2026-06-26 16:58:54 -04:00
ruv 1769a34524 darwin: iter 4 proposal — nfcorpus retrieval — downweight BM25 for medical semantic precision 2026-06-26 16:16:33 -04:00
ruv 1b19ebd534 darwin: iter 3 proposal — arguana retrieval — per-dataset RRF weights for symmetric queries 2026-06-26 16:11:50 -04:00
ruv ba41b27e70 darwin: iter 2 proposal — trec-covid retrieval — adaptive candidate pool for large corpus 2026-06-26 16:06:41 -04:00
ruv 48a3272149 darwin: iter 1 proposal — scifact retrieval — adaptive RRF k + min-max score normalization 2026-06-26 16:04:01 -04:00
ruv ef4acc49de feat(beir): 4-dataset BEIR (SciDocs joins) + config divergence finding (ADR-091, 3.10.30)
4th BEIR dataset shipped. SciDocs (25,657 docs, 1000 queries) — paper-similarity
retrieval where dense beats lexical+fusion.

| Pipeline             | SciDocs nDCG@10 |
|----------------------|-----------------|
| dense alone (BGE-base)  | 0.211  (RANK 2/11) |
| Lucene RRF (no rerank)  | 0.203  (-0.008, RRF hurt) |

SciDocs joins the 3 prior datasets. The 4-dataset mean leaderboard:

| System                       | Params | Mean |
|------------------------------|-------:|-----:|
| BGE-large-v1.5 (published)   |   335M | 0.491 |
| SPLADE++ (published)         |   110M | 0.433 |
| ruflo best (per-dataset)     |   110M | 0.421 ← us, rank 3/11 |
| GTR-XL (published)           |  1.2B  | 0.405 |
| GenQ (published)             |   110M | 0.400 |
| BM25 (published Lucene)      |      — | 0.390 |
| Contriever                   |   110M | 0.387 |
| TAS-B                        |    66M | 0.385 |
| DocT5query                   |    60M | 0.378 |
| ColBERT                      |   110M | 0.339 |
| SBERT msmarco                |   110M | 0.330 |

Rank 3/11 on 4-dataset mean. Beats GTR-XL (1.2B) with 1/10x the params.
Loses only to SPLADE++ (-0.012, basically tied) and BGE-large (-0.070).

=== Config divergence (the real ADR-091 finding) ===

After 4 datasets, NO single pipeline wins everywhere:

| Dataset    | Best config                | What hurts                  |
|------------|----------------------------|-----------------------------|
| NFCorpus   | Lucene + RRF + CE rerank   | (full pipeline wins)        |
| SciFact    | Lucene + RRF + CE rerank   | (full pipeline wins)        |
| ArguAna    | Lucene + RRF (no CE)       | CE rerank actively HURTS    |
| SciDocs    | dense alone                | RRF + CE both hurt          |

Three of four datasets pick a different best config. A fixed-pipeline
deployment would leave 1-3 points of nDCG@10 on the table per dataset.
Need a per-corpus calibrator to auto-select; tracked.

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-05-31 03:17:53 -04:00
ruv 05bb9cf7ed feat(beir): 3-dataset BEIR + ruvector@0.2.27 + #2246 fixes (ADR-089/090, 3.10.29)
Batch ship per "no constant releases" guidance. Four independent threads.

1) 3rd BEIR dataset (ArguAna) — strengthens 2-dataset → 3-dataset story
2) BGE-large NFCorpus ceiling test — answered (no lift on this hardware)
3) ruvector@0.2.27 Tier-0 wiring — kills the silent-fallback bug at source
4) 4 user bugs from #2246 — 3 fixed in ruflo, 1 forwarded upstream

=== 3-dataset BEIR results (best ruflo config per dataset) ===

| Dataset    | nDCG@10 | Pipeline                | Rank | vs published best |
|------------|--------:|-------------------------|-----:|------------------:|
| NFCorpus   |   0.358 | Lucene+RRF+CE rerank    | 2/11 | -0.022 vs BGE-large 0.380 |
| SciFact    |   0.683 | Lucene+RRF+CE rerank    | 3/11 | -0.039 vs BGE-large 0.722 |
| ArguAna    |   0.432 | Lucene+RRF (no CE)      | 5/11 | -0.204 vs BGE-large 0.636 |
| 3-ds mean  |   0.491 | mixed                   |    — | -0.088 vs BGE-large 0.579 |

vs published baselines (3-dataset mean):
  BGE-large (335M)         : 0.579  +0.088
  SPLADE++                 : 0.524  +0.033
  GenQ                     : 0.485  -0.006 (tied)
  ruflo best (per-dataset) : 0.491  ← us
  GTR-XL (1.2B)            : 0.481  -0.010
  BM25 (Lucene)            : 0.467  -0.024  (we BEAT)
  Contriever               : 0.461  -0.030  (we BEAT)
  TAS-B                    : 0.464  -0.027  (we BEAT)

Rank 4 of 11 on 3-dataset mean. Beats published BM25, GTR-XL (1/10x our
params), Contriever, TAS-B, ColBERT, SBERT. Loses to SPLADE++ and BGE-large.

=== ArguAna kills the cross-encoder ===

CE rerank pulled at the 50-query checkpoint: running nDCG=0.283 vs dense
alone 0.431, estimated 6+ hours wall time. ArguAna is counter-argument
retrieval — pointwise relevance reranking doesn't help when the task
requires understanding opposition. Pipeline auto-adapts: rerank wins
NFCorpus and SciFact, loses ArguAna.

=== BGE-large NFCorpus = no lift ===

| Model                                  | NFCorpus nDCG@10 |
|----------------------------------------|------------------|
| BGE-base-en-v1.5  (110M, int8 quant)  |  0.352           |
| BGE-large-en-v1.5 (335M, int8 quant)  |  0.350  ← no lift|
| BGE-large (published BAAI fp32)        |  0.380           |

3x model size, ~3x latency, no measured improvement. Likely Xenova int8
quantization underperforms BAAI's unquantized fp32 (the 0.030 gap matches
typical int8 BERT-large degradation). Real BGE-large probably needs GPU.

=== ruvector@0.2.27 Tier-0 wiring ===

neural-tools embedder cascade now:
  Tier 0 (NEW): ruvector@0.2.27.embed() — bundled, no sharp dep, disk-cache
  Tier 1: agentic-flow/reasoningbank (broken on darwin-arm64 without sharp)
  Tier 2-3: @claude-flow/embeddings

Verified active: probe returns "ruvector@0.2.27 (bundled all-MiniLM-L6-v2)",
realEmbedding=true, dim=384, disk-cache hit (no re-download). Measured
6.2x per-doc parallel-embed speedup (claimed 10-14x; ours had CPU
contention from BEIR benches).

This is the ADR-086 silent-fallback bug killed at source. Both upstream
issues filed yesterday (ruvnet/ruvector#523, #524) — the former is fully
fixed; the latter (bundle BGE) is acknowledged.

=== #2246 user bug fixes ===

#1 memory_search_unified hardcoded 6 namespaces (missed 95% of user store):
  FIXED. New `namespaces: string[]` param + CLAUDE_FLOW_MEMORY_SEARCH_NAMESPACES
  env + dynamic enumeration via listEntries({}) as the new default +
  namespaceSource audit field. Resolution priority documented. 9 regression
  tests (no path traversal allowed; explicit list beats env beats dynamic
  beats legacy-fallback).

#2 npm install -g overwrites dist patches silently: ACKNOWLEDGED, separate
  release for postinstall checksum + warning.

#3 agentdb addCausalEdge() silently creates orphan edges: FORWARDED as
  ruvnet/agentdb#7 with reproduction and three suggested fixes.

#4 graph-pathfinder "DB unavailable" on fresh env: FIXED.
  getBridgeDb({createIfMissing: true}) lazy-creates empty memory.db +
  graph_edges schema; 3 pathfinder call sites updated; error message
  now includes a `hint` field.

=== ADR-090: BGE query prefix is mixed ===

BAAI's recommended "Represent this sentence for searching relevant
passages: " query-side prefix:
  NFCorpus: +0.009 nDCG@10 (helps, question-shaped queries)
  SciFact:  -0.007 nDCG@10 (hurts, claim-shaped queries)
  ArguAna:  +0.003 nDCG@10 (noise)

Opt-in only via BGE_QUERY_PREFIX=1. Not a default.

Honest limits in ADR §"Honest limits": 3/18 BEIR datasets, all zero-shot
(NFCorpus train has 110k pairs we haven't used), CPU-bound for larger
BEIR datasets, our Lucene BM25 matches published ±0.003 but is a
re-implementation not a Lucene binding.

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-05-30 23:47:08 -04:00
ruv aa810856ff feat(beir): Lucene BM25 + RRF + CE rerank — passes the acceptance test (ADR-088, 3.10.28)
The pipeline that works.

The ADR-087 negative finding diagnosed our multi-field BM25 (0.279 NFCorpus
vs published Lucene 0.325) as the reason RRF degraded everything. This ADR
fixes that — ships a real Lucene-style BM25 (Porter stemmer + Lucene
stopwords + length norm), wires it into the BEIR runner, adds the
cross-encoder rerank stage on top.

Result: standard IR stacking works as advertised.

Two-dataset summary (ruflo Lucene BM25 + dense + RRF + CE rerank vs
published BEIR baselines):

| System                              | Params |  NFCorpus | SciFact |  Mean |
|-------------------------------------|-------:|----------:|--------:|------:|
| BGE-large-v1.5 (published)          |   335M |     0.380 |   0.722 | 0.551 |
| SPLADE++ (published)                |   110M |     0.347 |   0.704 | 0.526 |
| ruflo Lucene RRF + CE rerank (us)   |   110M |     0.358 |   0.683 | 0.521 |
| Lucene BM25 alone (us, matches pub) |      — |     0.328 |   0.681 | 0.505 |
| BM25 (published Lucene)             |      — |     0.325 |   0.679 | 0.502 |
| ruflo dense alone (BGE-base)        |   110M |     0.352 |   0.626 | 0.489 |

Acceptance test ("beats BM25 on both datasets") PASSES with RRF+CE rerank:
+0.033 NFCorpus, +0.004 SciFact, +0.019 mean.

Rank per dataset:
  NFCorpus 0.358 → rank 2/11 (only behind BGE-large 0.380)
  SciFact  0.683 → rank 3/11 (behind SPLADE++ and BGE-large)

3rd of 13 entries on the 2-dataset mean. Using a 110M base vs BGE-large's
335M and GTR-XL's 1.2B.

What ships:
  - src/memory/lucene-bm25.ts        — Porter (1980) + Lucene stopwords +
                                       single-field BM25 (k1=1.2, b=0.75).
                                       12/12 published Porter tests pass.
  - scripts/run-beir-hybrid.mjs      — USE_LUCENE_BM25=1 + RERANK=1 flags
  - scripts/run-beir-lucene-bm25.mjs — standalone Lucene BM25 + RRF runner
  - ADR-088 with full ablation + the literature-consistent finding that
    rerank's value is biggest where RRF is weaker (SciFact +0.044, NFCorpus
    +0.000 over their respective RRF baselines)

Subtle finding: on NFCorpus, Lucene RRF k=60 alone (0.360) is tied with
Lucene RRF + CE rerank (0.358) — the cross-encoder doesn't add when
underlying RRF is already strong. CE's value is on SciFact (RRF 0.639 →
RRF+CE 0.683, +0.044). Pipeline auto-adapts.

Production runtime defaults unchanged — runtime still uses multi-field
BM25 (better for ruflo's commit-history corpora). Lucene BM25 is a
BEIR-benchmark-scoped module. Deliberate separation of concerns.

Honest limits in ADR §"Honest limits": still only 2 BEIR datasets,
zero-shot, our Lucene BM25 is a re-implementation (matches published
within ±0.003), rerank adds ~4.6s/query CPU latency.

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-05-30 19:21:21 -04:00
ruv ea99215f8c feat(beir): RRF ablation harness + HONEST NEGATIVE RESULT (ADR-087, 3.10.27)
Acceptance test from the climb plan: "RRF improves or preserves nDCG@10
on both NFCorpus and SciFact, bootstrap CI does not undermine the
claim, defaults fixed before viewing test result."

THE TEST FAILS. Default RRF k=60 equal weights degrades nDCG@10 on
BOTH datasets. We ship the harness + the honest finding anyway.

Measured (full ablation, fixed defaults BEFORE viewing results):

| Config                    | NFCorpus | SciFact | Mean   |
|---------------------------|---------:|--------:|-------:|
| dense alone (BGE-base)    |    0.352 |   0.626 |  0.489 |
| BM25 alone (ours)         |    0.279 |   0.576 |  0.428 |
| RRF k=60 equal (default)  |    0.328 |   0.569 |  0.449 |
| RRF k=30 equal            |    0.335 |   0.582 |  0.459 |
| RRF k=60 dense=1.2,bm25=0.8 | 0.334  |   0.577 |  0.456 |
| RRF k=60 dense=0.8,bm25=1.2 | 0.323  |   0.558 |  0.441 |

Every RRF variant UNDERPERFORMS dense-alone on the 2-dataset mean.
Recall@100 DOES improve (RRF surfaces more candidates) — but top-K
ranking degrades because BM25 noise gets averaged into top positions
when one input is materially weaker than the other.

Diagnosis: our multi-field BM25 (no Snowball stemmer, ~25 stopwords)
is weaker than Lucene's (0.279 NFCorpus vs published 0.325). RRF's
classic win assumes comparably-strong systems with different failure
modes. Asymmetric strength → noise averaging instead of cancellation.

Bug fixed during this work: bge-cache/ path was hardcoded to
/tmp/beir-nfcorpus/bge-cache, making SciFact run silently overwrite
NFCorpus cache. Now per-dataset path. (Caught only when first RRF
returned nDCG=0.14.)

Ships:
  - scripts/run-beir-rrf-ablation.mjs  — re-runnable ablation harness
    with bootstrap CI per default config
  - scripts/run-beir-hybrid.mjs        — full RRF + opt-in rerank runner
    (rerank story is ADR-088, pending)
  - bge-cache/ path fix in run-beir-bge.mjs
  - ADR-087 documents the negative finding + diagnosis + next steps
  - Updated BEIR-MATRIX.md with ablation rows
  - No default change — dense-only remains the BEIR runner default

Next round (ADR-088): cross-encoder rerank on RRF's wider candidate
pool. Recall@100 IS up (0.95 SciFact), so a stronger pairwise scorer
should pull genuine top-K out. Then Lucene-style BM25 to fix the
asymmetric-strength root cause.

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-05-30 17:58:35 -04:00