Commit Graph
4 Commits
Author SHA1 Message Date
osobhandClaude Opus 5 29baabbed2 feat(agent): selectable fusion; adopt the measured 0.4/0.6 default weights
BENCHMARKS.md has recorded since the weight sweep that the 0.7/0.3 default is
strictly dominated by 0.4/0.6 over the full LongMemEval haystack, but the
shipping code never adopted it: unified_search and the OpenClaw backend both
passed 0.7/0.3. Re-running the sweep here (500 questions, real MiniLM
embeddings on a GPU) reproduces it — turn-level Hit@1 51.6% vs 44.2%, Hit@5
81.4% vs 79.2%, Hit@10 87.8% vs 85.8%, MRR 0.6430 vs 0.5856 — so both now use
hybrid::DEFAULT_FUSION, which is that operating point and carries the
reasoning. A unit test pins it.

Fusion is also selectable now. hybrid::Fusion is either Weighted { vector,
keyword } or Rrf { k }; hybrid::fuse applies either to one candidate list per
stage, and merge_vector_keyword / hybrid_search delegate to it, so the public
API is unchanged. New HDF5Memory::hybrid_search_with and
hybrid::hybrid_search_fused take a Fusion. Reciprocal rank fusion was
implemented but reachable only as a free function over a linear scan, so it
had never been compared with the weighted sum on equal terms; it is now a mode
in the LongMemEval bench (measurement to follow).

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-09-19 16:57:51 -07:00
osobhandClaude Fable 5.1 99b907be04 feat(agent): single-writer lock, read-only open, recoverable WAL
- HDF5Memory::create/open take an exclusive advisory lock on <store>.h5.lock
  (std File::try_lock, no new dependency). The store lives in memory and is
  rewritten wholesale at each checkpoint, so two handles on one store used to
  silently destroy each other's data; a second writer now gets
  MemoryError::Locked. The OS drops the lock with the descriptor, so a crash
  never leaves a stale lock. Acquisition retries for ~250 ms to absorb a
  previous owner that is mid-teardown; AsyncHDF5Memory::shutdown releases the
  lock once its writer task has stopped.
- HDF5Memory::open_read_only: a lock-free, point-in-time view (checkpoint +
  current WAL contents, replayed in memory) that never writes — it does not
  repair, upgrade or move the WAL, and anything that would persist returns an
  error. The CLI's recall/stats/agents-md/export use it, so a store can be
  inspected while an agent has it open. Tests that reopened a store purely to
  verify on-disk state now use it.
- open() no longer fails on a WAL that cannot possibly be replayed (torn
  header, bad magic): it is moved to <store>.h5.wal.corrupt-<ts>, reported via
  HDF5Memory::quarantined_wal(), and the healthy .h5 opens from its last
  checkpoint. A well-formed header with an unknown version still fails and is
  left untouched — most likely a newer build's WAL, which must not be
  discarded.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-19 06:07:21 -07:00
Omar Sobh d1f74702c0 refactor: use std::io::Error::other() instead of Error::new(ErrorKind::Other, e) 2026-05-21 09:40:53 -07:00
redclawsystems 3f222f6956 Merge pull request 'docs(clawhdf5): document DType variants, fix unresolved doc links' (#17) from sdlc-docs/clawhdf5-types-20260514-165210 into main 2026-05-14 23:54:48 +00:00